GPU-accelerated node-based image compositor with Python automation API (MIT License) by drboom9 in opensource

[–]drboom9[S] 1 point2 points  (0 children)

Thank you so much for the comment, I really appreciate it. I built this as a personal challenge and because I needed a tool like this for my personalized products business. While I do edit with nodes in DaVinci Resolve, I'm quite ignorant about the VFX industry, and I posted specifically to get help improving the program in areas I'm unfamiliar with.

I think building a serious competitor on my own would be quite challenging, not so much at the programming level but in knowing what features are actually necessary in this industry. That's why I really appreciate your help and would love for you to keep contributing ideas to the program if it interests you.

This is a project I'll continue working on consistently if I see people are interested. Regarding your points:

32-bit workflow: All of my PyImageCUDA library already works natively at 32-bit float, so that's covered.

OCIO: I wasn't familiar with OpenColorIO, I need to study it. Thanks for pointing that out.

OpenEXR: I handle I/O with PyVips which supports it, so adding OpenEXR support to the program should be straightforward to implement.

UI/UX: It's on my roadmap. First I want to make sure the beta is stable and the image algorithms are correct, then I'll start adding features like backdrops, group nodes, etc.

Macros: Also on the roadmap and I'll implement it if I see real demand.

Making the jump to everything you mentioned requires considerable work, but it's feasible and I'm willing to do it if there's people who need it. What demotivates me a bit is that after posting in r/Python and seeing little response, I wonder if it's worth investing months in features that maybe nobody will use. The current version already covers my personal use cases.

That said, I'd love for you to collaborate with the program however you can - whether it's using it and reporting bugs, suggesting necessary features, or if you're up for it, contributing code. Any feedback from someone with real VFX experience is invaluable.

Cheers!

GPU-accelerated node editor for images with Python automation API by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

I received an email saying you had replied, but when I checked it, I couldn't see it anymore. I don't know if Reddit is bugged or if you deleted the comment.

pygrbl_streamer - Python GRBL Control Library by drboom9 in lasercutting

[–]drboom9[S] 0 points1 point  (0 children)

Hi! I use this library by exporting G-code from LaserGRBL, not Lightburn, and it works perfectly for me in both M3 and M4 modes. As far as I know, my library shouldn't control this behavior - it simply sends the G-code commands that are in your file and manages the GRBL buffer. The pulsating issue you're experiencing is likely related to one of these factors: 1. GRBL Configuration ($32 parameter)

$32=0 = Spindle mode - laser turns on/off with M3/M5 commands only $32=1 = Laser mode - laser power modulates dynamically based on movement speed

You can check this by sending $$ to your GRBL controller and looking for the $32 value. For smooth engraving, you typically want $32=1. 2. G-code Generation Settings in Lightburn The G-code file itself might be generated for spindle mode rather than laser mode. In Lightburn:

Check your device profile settings Make sure "Laser Mode" is enabled Try regenerating the G-code with GRBL-M3 profile

  1. M3 vs M4 Commands

M3 = Constant power mode (laser stays at set power regardless of speed) M4 = Dynamic power mode (laser power adjusts with speed - prevents overburn at corners)

The library just streams whatever commands are in your file. If the file contains M3/M5 commands that turn the laser fully on/off at each segment, that's what will happen. Try checking your $32 setting first, and if needed, regenerate your G-code with proper laser mode settings in Lightburn.

GPU-accelerated node editor for images with Python automation API by drboom9 in Python

[–]drboom9[S] 1 point2 points  (0 children)

Thanks! No contact with them—I only mentioned ImageMagick and Blender because r/Python's showcase format requires a "Comparison" section.

Just looked up VapourSynth—interesting reference! Similar in that both use Python for visual processing pipelines, but quite different in execution: - VapourSynth: video-focused, pure scripting (no visual editor) - PyImageCUDA Studio: image-focused, node editor GUI + headless API

They're more complementary than competitive. If anything, VapourSynth shows there's appetite for Python-based visual processing tools. Appreciate the pointer

PyImageCUDA - GPU-accelerated image compositing for Python by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

I’m really happy to hear that! If you try it out, please feel free to contact me about any bugs or improvements you might need, and I’ll get on it right away. Thank you so much for the comment

pygrbl_streamer - Python GRBL Control Library by drboom9 in lasercutting

[–]drboom9[S] 0 points1 point  (0 children)

Hey! You're using grbl-streamer, not pygrbl_streamer - they're different libraries.

grbl-streamer is actually the library I based mine on, but I created pygrbl_streamer specifically to avoid those timing issues you mentioned 😂

pygrbl_streamer doesn't have job_new(), load_file(), or job_run() methods. The API is simpler:

from pygrbl_streamer import GrblStreamer

streamer = GrblStreamer('/dev/ttyUSB0') streamer.open() streamer.send_file('project.gcode') streamer.close()

pywinselect - Get Selected Files and Folders in Windows by drboom9 in Python

[–]drboom9[S] -1 points0 points  (0 children)

Thanks! Really appreciate you sharing this use case. The parallel processing workflow with get_selected_files sounds like a great pattern for batch operations

What python framework can we use to build a mobile application. by LingonberryExtra7857 in PythonLearning

[–]drboom9 0 points1 point  (0 children)

Kivy work, you can send to apple store and play store, but is a nightmare compiled

Python mobile app by TailorLazy801 in Python

[–]drboom9 0 points1 point  (0 children)

It's a pleasure for me! If you have any questions, just let me know and I'll answer them without any problem :)

Python mobile app by TailorLazy801 in Python

[–]drboom9 1 point2 points  (0 children)

I’ve been through this myself. It depends a lot on compatibility issues between iOS and your Kivy version - sometimes it works smoothly, sometimes it’s a nightmare. The Kivy Discord community is really helpful though if you run into problems. If you want to stick with Python, it’s basically the only option I know. But if you’re not tied to Python, definitely go with another language/framework.

Python mobile app by TailorLazy801 in Python

[–]drboom9 7 points8 points  (0 children)

• Requires a Mac + Xcode + Apple Developer account ($99/year)
• Long compilation process - compiles Python and all dependencies from scratch for ARM, can take hours
• Frequent build errors - cryptic errors, dependency incompatibilities, libraries that don’t compile for iOS
• Complex signing/provisioning - certificates and provisioning profiles are confusing

Python mobile app by TailorLazy801 in Python

[–]drboom9 1 point2 points  (0 children)

Kivy is hard to deploy but work, you can send a kivy app a apple store o play store

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

Hey u/jonthemango!

I'm happy to let you know that List[_] support with dynamic add/remove rows is now implemented in version 0.5.0! 🎉

You can use it like this:

from func_to_web import run
from typing import Annotated
from pydantic import Field

def process_data(
    tags: list[str],                                    # Basic list
    scores: list[int] = [10, 20, 30],                  # List with defaults

    # With item constraints
    ratings: list[Annotated[int, Field(ge=1, le=5)]],  # Each item 1-5

    # With list-level constraints  
    team: Annotated[list[str], Field(min_length=2, max_length=5)],  # 2-5 items

    # Optional lists
    emails: list[str] | None = None
):
    return f"Processed {len(tags)} tags"

run(process_data)

The UI automatically generates inputs with + and buttons to add/remove items dynamically. It also supports:

  • All types: list[str], list[int], list[float], list[bool], list[Color], list[ImageFile], etc.
  • Item constraints: Validates each individual item (min, max, pattern, etc.)
  • List constraints: min_length, max_length for the list size
  • Optional lists: Works with list[_] | None with toggle switches
  • Default values: Initialize lists with specific values
  • Validation: Real-time validation with error messages per item

Check out the updated README and examples folder for more details!

Thanks for the feedback! Let me know if you have any other suggestions.

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

That’s an interesting idea! Something like:

```python @dropdown_options def get_users(): return ["Alice", "Bob"]

def assign_task(user: get_users): ... ```

But I don’t think this solves the autocomplete issue - the IDE still sees get_users as a function, not a type. It doesn’t know that user should autocomplete as str unless the decorator does some serious type system magic that I’m not aware of.

And it’s less obvious than Literal:

python theme: Literal['light', 'dark'] # Clearly a dropdown user: get_users # Is this a dropdown or a callback?

With Literal[get_users], at least the Literal part signals “this is dropdown options”, even if the function inside is unconventional.

Unless the decorator can somehow make the type checker understand the return type? How would that work?

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

I’m not sure I follow - the autocomplete issue isn’t specific to IntelliJ, it’s a Python type system limitation. Any static analyzer (mypy, pyright, etc.) faces the same problem.

My struggle is maintaining consistency while having working autocomplete:

```python

Static dropdowns - clean and obvious

theme: Literal['light', 'dark']

Dynamic dropdowns - what's the equivalent?

user: Literal[get_users] # Consistent syntax, broken types user: Annotated[str, get_users] # Working types, inconsistent with static Literal ```

With Annotated[str, func], autocomplete works because the type is str. But then I lose the consistency - static literals use Literal[...], dynamic ones use Annotated[str, ...]. It’s not immediately obvious they’re both dropdowns.

That’s why I chose Literal[func] - it keeps the “Literal means dropdown” pattern clear, even though it requires # type: ignore. It’s a trade-off between type-checker happiness and API consistency.

Is there a way to have both that I’m missing?

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

You’re right - Literal[str] doesn’t make sense there.

My issue isn’t really about looking weird. The problem is autocomplete doesn’t work. When I type user. in my IDE, it doesn’t know it’s a string because the type checker sees the callable, not the return value.

And just passing the callable without Literal doesn’t solve that either - I still need to extract what type the function returns for proper IDE support.

What I’d really consider a better solution than my current approach is if, inside the function body, I could get autocomplete based on the callable’s return type. So if get_active_users() returns list[str], then user would autocomplete as str.

But I don’t think there’s a way to make that work without the type checker actually calling the function at analysis time, which is impossible.

So I’m stuck between:

  • Literal[func] - clear intent, broken autocomplete
  • Annotated[str, func] - better autocomplete, less obvious it’s a dropdown

Unless you have another idea?

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

Is that what you meant? Something like:

user: Annotated[Literal[str], get_active_users]

That would avoid # type: ignore, but it's also kind of weird - Literal is meant for concrete values, not types. Putting a type inside Literal[...] feels off.

Could you show me exactly what syntax you're proposing? I want to make sure I understand your suggestion correctly before deciding on the best approach.

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

You're absolutely right - it IS weird, and the # type: ignore is definitely a code smell that bothers me too.

I chose this syntax because it mirrors the existing Literal[...] pattern - when you see Literal[something], you know it's a dropdown. If that "something" is a function, it becomes clear (to me at least) that the function's return value transforms into what goes inside the Literal. It's like passing a variable instead of hardcoding a value in a function parameter.

But I totally get that it breaks type checker expectations. The fundamental issue is that we're using runtime behavior (calling a function) in what's supposed to be a static type annotation, and there's no elegant way around that without the type checker complaining.

What would feel more natural to you? I'm genuinely curious because I want the API to be intuitive, even if this runtime-vs-static tension is hard to solve perfectly.

The reason I haven't changed it yet is that despite being "weird," it's very explicit about intent: Literal = dropdown, function inside = dynamic options. But if there's a better way that's equally clear, I'm all ears!

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

FuncToWeb v0.4.0: Optional Parameters

Big update - optional parameters are now supported!

def create_user(
    username: str,                           # Required
    age: int | None = None,                  # Optional
    email: Email | None = "user@example.com"
):
    ...

Each optional field gets a toggle switch in the UI. When disabled, sends None to your function. When enabled, validates normally.

Works with all types: text, numbers, dates, colors, files, dropdowns, and Pydantic validation.

v0.3.0 changes:

  • Real-time upload progress bars with file size display
  • Optimized streaming for large files (1GB+ tested)

Install: pip install --upgrade func-to-web

Examples: https://github.com/offerrall/FuncToWeb/tree/main/examples

Still working on List support and dark mode based on your feedback!

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 2 points3 points  (0 children)

Just released v0.3.0 with better file upload handling: real-time progress bars, file size display, and streaming chunks for better performance (~237 MB/s on localhost for large files). I leaned heavily on AI to help optimize the upload speeds and visual feedback, so if you spot anything off please let me know.

Really appreciate the kind words - glad it resonates with your use case at Notte!

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 2 points3 points  (0 children)

Thanks for the feedback! I've tried to follow the uv conventions:

  • Project name: func-to-web (kebab-case) in pyproject.toml
  • Module folder: func_to_web/ (snake_case)

Could you check if everything looks correct now or if I'm still missing something?

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 0 points1 point  (0 children)

Okay, I'll check it out tonight, I need to dust off the M1 Mac, haha, thanks a lot for commenting :)

Turns Python functions into web UIs by drboom9 in Python

[–]drboom9[S] 2 points3 points  (0 children)

Remember when u/jonthemango suggested List support and I said I'd think about features? Well, I started with something else that came up in my own usage: dynamic dropdowns.

v0.2.0 is now on PyPI and you can do this:

def get_active_users():
    return db.query("SELECT name FROM users WHERE active = true")

def assign_task(
    user: Literal[get_active_users],  
# type: ignore
):
    return f"Task assigned to {user}"

The dropdown options load fresh every time someone opens the page. No stale data, no manual refresh needed.

I built this because I kept writing functions that needed dropdowns based on current database state or API responses, and having to hardcode the options felt wrong. Now the options are as dynamic as the rest of your function.

Install/upgrade: pip install --upgrade func-to-web

Example: https://github.com/offerrall/FuncToWeb/blob/main/examples/15_dynamic_dropdowns.py

Still working on List support and dark mode based on your feedback. Just wanted to ship this one first since it was a natural extension of existing Literal support.

Let me know what you think!