From c225a0119e52f8c644b139890caadbb5e19e2a6d Mon Sep 17 00:00:00 2001 From: ControlAltAI Date: Thu, 15 Aug 2024 21:26:45 +0530 Subject: [PATCH] Initial commit --- __init__.py | 15 ++++ __pycache__/__init__.cpython-312.pyc | Bin 0 -> 551 bytes .../flux_resolution_cal_node.cpython-312.pyc | Bin 0 -> 2242 bytes __pycache__/flux_sampler_node.cpython-312.pyc | Bin 0 -> 2720 bytes flux_resolution_cal_node.py | 52 +++++++++++++ flux_sampler_node.py | 70 ++++++++++++++++++ pyproject.toml | 13 ++++ 7 files changed, 150 insertions(+) create mode 100644 __init__.py create mode 100644 __pycache__/__init__.cpython-312.pyc create mode 100644 __pycache__/flux_resolution_cal_node.cpython-312.pyc create mode 100644 __pycache__/flux_sampler_node.cpython-312.pyc create mode 100644 flux_resolution_cal_node.py create mode 100644 flux_sampler_node.py create mode 100644 pyproject.toml diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e7a3980 --- /dev/null +++ b/__init__.py @@ -0,0 +1,15 @@ +from .flux_resolution_cal_node import FluxResolutionNode +from .flux_sampler_node import FluxSampler + +print("Initializing Flux Resolution Node and Flux Sampler Node...") + +# Registering the nodes +NODE_CLASS_MAPPINGS = { + "FluxResolutionNode": FluxResolutionNode, + "FluxSampler": FluxSampler, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "FluxResolutionNode": "Flux Resolution Calculator", + "FluxSampler": "Flux Sampler", +} \ No newline at end of file diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccfce0ec8c55da4ce3d452b1a00dcf5fb5752e60 GIT binary patch literal 551 zcmZ8dF-yZh82v73YEe6A2c-q6V+D(dpcD~ftP;>z4GxyV5qhZvF1d0^!1j;0_y@$* z(SP8g;2;49adNA=IeC}13Vy@g``){E@8i4A=O;nb=j&bP76H7;W?bqBd~FMG2?PkD z;G-r&5-U{k)uxI-0XIX`8{w9Pz(uY~GFM7dBO1x3DBGK;u9%* zjRW1b@uA*mnAX0X6jO57v>ONd8MgGp`mc5kU&0OF_HnIcFu&6~HODtzU0GclH?4LY zM$AtG!!d~s7DSv;okqHet1J=S7Cxd$=Z!fr=1%fsGef qdIjwvyYmFbAP1%8=fc8=rp_r3P#8=@Y5lpdDEbBE5sG|D7=Hk&j-*cj literal 0 HcmV?d00001 diff --git a/__pycache__/flux_resolution_cal_node.cpython-312.pyc b/__pycache__/flux_resolution_cal_node.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..29a893ff3536bee3e109fd58dbd77348f1b915f7 GIT binary patch literal 2242 zcmZuyO-vg{6rSDnn)R-U4cM`v334KmcoQICej2Q(KnV#}iJ{n3!lhbS-ZeN{+hlj0 zfMr)4IJh@%p??zUi7Gwh+C!z>d-2MLSSt=lJyf|lrBW+SeY5_FNf~M1yzl+Zo0<1! zfA8#M5sc*OZ^^$q5c&gy=CCxFQ$H{-5Q!ck5$z$7cuCeZG2kVXB4UI{h$PJ94#is% zO@BN$EYayCfEP$YV2fg;M2W;6dfBjySwu2Mi&V@iT4Eg{9b-gm%qDj1p%}Zv@HV6S zp`6=Zk<_f5(^A?Hy z?>MuM21kAV$kSY0k@)IJ>$Ac5+@I>%lJ9bP3M+&xVj}JG(m~OMg5F;!k`kes^ZJ?oh3dGuFqxD z$(_|ua~1+4f$=6-PvlfBn-(%~ziLw`%w;p0l9gv=Z8jv}t5?^PP!599ss|wvmrbYP ztsR34g_l>OLUe6;K9cYMf8h+b>2Y-FxM z9l84tzApC+*E+4&M&8l3-b*!#bFwwW+1OKXMm%Lup>R}j0&iF&(Unm65y)sbNNv-w zZc3?*P0e86Cv3PN<3vu5Ymy+Q(o#l+s#f!!_O1HNt=`2Oh$e7xHwP{@v)I3YQ+(_C6)i=&K!}z+ z#3@<})`F!#V?NIzXu3QUNU=kMhoup@qhMM#BNdr*I@7bIvq4ra7RpDURjvSeJA;W2NS^X- z`*_-*lX5n$8ML}3r!<2~$F~eBl>vd0&1FR1Zdg=FPAYhd3VxuC&P*;XDXB!gu?)^E ztp>2y3#^H>tOo61wxep;TIHp5<6u2F7-Oy?Xj#PtP_+Z`wGE{cTe^YdZ(Yzo7nQCD z$2kGAi;i8r2YkgfP_mtP2i|yZ>)zW(V-@e+SA^~jlsbfB(}<1H;zIoAQJbJwe$-ftF8JiVobW2bvxI@r`N z->f)q9r<-<00+6e|Ll;_J^o4;f3%=?jhCz^-mCl14-$tr54~mg?Gjscxb~9=Ps$E| znei(Q*kqXJ3`P(#@w6le1}g~ZteBHAZx;l3{pE&+OUQ9mO-tHlR#Yy5qhVi}kFKtS z>#tJ_g=ZhnM-1lSYIrUhT7tjQ+-!9I(bCGA!7Z&u@oN@ddN6O^hyrzv%p~f!gqvK! z1oyQ%4rC8iY3DoAPP3;JvUb%lSG$5-gS(5>o^c?K8@mfthaX7y<=xLtEpD2x2gG6W zefY+G@Bg*FxyDPCRl+=FE@kxKbcDIZ*+@iqJiELM&t1gmGldUAk>$nNH34s_rTZZ1 zGv1|d&_-;HH!3*WzpVU#Gne~6| C=TN8s literal 0 HcmV?d00001 diff --git a/__pycache__/flux_sampler_node.cpython-312.pyc b/__pycache__/flux_sampler_node.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f90586b57be600308ea8a09b393f00633218ba85 GIT binary patch literal 2720 zcmaJDOKcn0@$D{`T#-wOAAKUpktxTHO{Z0A#ztMsb;3xLM1-PLkuq#n@M6Wcq*mS~ zncbxtt1DCo9T@bG=A;%d(4r>?4ho?sT?z<273hV84yjhn`0f!b$D0K zRYaKmBa`C+bAa6}nn&2RhcN$~ZClEDFt2!2CMRGXy8-t-VWOVbRG5zX39nQ&#UQQ? zrCK5$3M-Wu;c-QmVr0NUl3dCwre(+);WXVO0_;{QQcNejS}9?jcpM~c5f@fe6ChS~ z;;xodsgft&HkQ^mVo{#BO;xXG3UQaph7JaOW>J?wqW~-s>A@c7T30MN-wvV;I}xFi z81VZ@aq^O56%I3d=y^vo=fZ4`$6U^hT{L!x+r5V%YEM)kzB#S>Sw^NV7Ryiu3{55WU;+0%?SY4E9_ zG8q&NrHNoDpH@{v!BK|ri%YYK6cFOfQhGL-O)jOA>G`i1;!ef0iFB55$#nMhAb9Ya zda4GlA{6C_2P*}+s#%27)e->tGs4fMmg3oewS8@USnN7o{N>=E=Krz1_hHm!L}1gH zq~H<&;xa9zV$g^*9>9Np)&312ND{A?v7!+%UoK(QQp+W^R3xG%TT022R9!AAL^Rtu zluEL$kUlfNp=UU;&a>|!bQqu9+ZvzD)#R#}%y;I-M^lxE5$%P4Dc z&59?bv?D6Ox0ia3!`4*g3GpS<%d1%_`*1mt*&aFbJf_YF`oR%%4ZtpHxsiXQIr>gB za-$h}@73f7^~kMP6S4Z+H=AP@pRF7+M^_q?3-!@t^TIm^;ls?|!u9*P#+9Gf$Jd${ zFCR=E#_Mwr8t*==PvqVN`$qd)oG;*QAzz>O1neVY8~{Y`Zl@dS#Yyz`$k})zPCV~Z zXY}qa?y3{GAe)i4`oVj!GRHsXA4tJ?jETWx&?cJmeK3HfAtYTk9}^)jYudV;e+<1>HRW|pkt*vlj02}& zMZ)K4;gNvT5#UG(ieHB|KmtX@k}NR40hS%tgpO-4A3n*ny906M%atd_E$WNEVki~a zP@qg{U+C|&6WHBSm0yrRSKM=muUe{RlELMbrTLXaCL?_uUy%~&_{XWlY&1+g)C$JC zVA_Dbh@60pD5ad#(5yN6F@8v?A5(Cff|~#c-*!T%luc-GTM7|MN>Qei@l&dFkAk02 zO|D$E%rH=q?=Ry9Rin{uht4*Rb|Pq-HCq67(W~I_aqwy*c=b4VyAizoB6z3f{Z(RKHV6fu8&OD#BV~Q)SW*JJrfSD9dY%QN6nkJkF5IrN6o1_ zM`JA>g(puC8(w6<9{~*veewA7$G_HVTyr#1<7&yz`@ac}n2 zn1LBNzqInu$^Tc#xwQR3Xw4cF&=NJ@2e5~leBcc$^4=2;xq~fAwJxB+i@T|2cmlw{ z$nHXO;M(rOiR%JC+_pt6Y>V`}MmoC1D;0qop86E#e2ph5YXvp zegdGyF%0t(4ZTF-OB4p;TNgLX)=}tNFM2D()Y0I7TsN5EHwZv$gF$@gH`6VS9RZba Q%S+jNz)r9YH0E6PKVe+Sc>n+a literal 0 HcmV?d00001 diff --git a/flux_resolution_cal_node.py b/flux_resolution_cal_node.py new file mode 100644 index 0000000..b67066f --- /dev/null +++ b/flux_resolution_cal_node.py @@ -0,0 +1,52 @@ +class FluxResolutionNode: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "megapixel": (["0.1", "0.5", "1.0", "1.5", "2.0", "2.1", "2.2", "2.3", "2.4", "2.5"], {"default": "1.0"}), + "aspect_ratio": ([ + "1:1 (Square)", + "2:3 (Portrait)", "4:5 (Portrait)", "5:8 (Portrait)", + "9:16 (Portrait)", "9:19 (Tall)", "9:21 (Tall)", "9:32 (Tall)", + "3:2 (Landscape)", "5:4 (Landscape)", "8:5 (Landscape)", + "16:9 (Landscape)", "19:9 (Ultrawide)", "21:9 (Ultrawide)", "32:9 (Ultrawide)" + ], {"default": "1:1 (Square)"}), + } + } + + RETURN_TYPES = ("INT", "INT", "STRING") + RETURN_NAMES = ("width", "height", "resolution") + FUNCTION = "calculate_dimensions" + CATEGORY = "ControlAltAI Nodes/Flux" + OUTPUT_NODE = True + + def calculate_dimensions(self, megapixel, aspect_ratio): + megapixel = float(megapixel) + # Extract the numeric ratio + numeric_ratio = aspect_ratio.split(' ')[0] + width_ratio, height_ratio = map(int, numeric_ratio.split(':')) + total_pixels = megapixel * 1_000_000 + dimension = (total_pixels / (width_ratio * height_ratio)) ** 0.5 + width = int(dimension * width_ratio) + height = int(dimension * height_ratio) + + # Determine rounding factor based on megapixel value + if megapixel in [0.1, 0.5, 1.0, 1.5]: + round_to = 8 + if megapixel in [1.0, 1.5]: + round_to = 64 + else: # 2.0 and above + round_to = 32 + width = round(width / round_to) * round_to + height = round(height / round_to) * round_to + + resolution = f"{width} x {height}" + return width, height, resolution + +NODE_CLASS_MAPPINGS = { + "FluxResolutionNode": FluxResolutionNode, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "FluxResolutionNode": "Flux Resolution Calculator", +} diff --git a/flux_sampler_node.py b/flux_sampler_node.py new file mode 100644 index 0000000..5e9c40b --- /dev/null +++ b/flux_sampler_node.py @@ -0,0 +1,70 @@ +import comfy.samplers +import torch +import comfy.sample +import latent_preview + +FLUX_SAMPLER_NAMES = [ + "euler", "heun", "heunpp2", "dpm_2", "dpm_2_ancestral", "lms", "dpmpp_2m", + "ipndm", "ipndm_v", "deis", "ddim", "uni_pc", "uni_pc_bh2" +] + +FLUX_SCHEDULER_NAMES = ["simple", "normal", "sgm_uniform", "ddim_uniform", "beta"] + +class FluxSampler: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "model": ("MODEL",), + "conditioning": ("CONDITIONING",), + "latent_image": ("LATENT",), + "sampler_name": (FLUX_SAMPLER_NAMES,), + "scheduler": (FLUX_SCHEDULER_NAMES,), + "steps": ("INT", {"default": 20, "min": 1, "max": 10000}), + "denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), + "noise_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), + } + } + + RETURN_TYPES = ("LATENT",) + RETURN_NAMES = ("latent",) + FUNCTION = "sample" + CATEGORY = "ControlAltAI Nodes/Flux" + + def sample(self, model, conditioning, latent_image, sampler_name, scheduler, steps, denoise, noise_seed): + device = comfy.model_management.get_torch_device() + + # Create sampler + sampler = comfy.samplers.KSampler(model, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=denoise) + + # Prepare latent + latent = latent_image.copy() + latent_image = latent["samples"] + + # Prepare noise + noise = comfy.sample.prepare_noise(latent_image, noise_seed) + + # Prepare conditioning + positive = conditioning + negative = [] # Empty list for negative conditioning + + # Sampling + callback = latent_preview.prepare_callback(model, steps) + disable_pbar = not comfy.utils.PROGRESS_BAR_ENABLED + + samples = sampler.sample(noise, positive, negative, cfg=1.0, latent_image=latent_image, + force_full_denoise=True, denoise_mask=None, callback=callback, + disable_pbar=disable_pbar, seed=noise_seed) + + out = latent.copy() + out["samples"] = samples + + return (out,) + +NODE_CLASS_MAPPINGS = { + "FluxSampler": FluxSampler +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "FluxSampler": "Flux Sampler" +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e89b37d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "ControlAltAI Nodes" +description = "Quality fo Life Nodes from ControlAltAI. FLux Resolution Calculator and Sampler." +version = "1.0.0" +license = { file = "LICENSE" } + +[project.urls] +Repository = "https://github.com/pythongosssss/ComfyUI-Custom-Scripts" + +[tool.comfy] +PublisherId = "ControlAltAI" +DisplayName = "ControlAltAI Nodes" +Icon = ""