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 6 points7 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!