Size Qwen 2.1 Generate from the bench aspect table.

Wire EmptyLatentImage to the official ~1 MP grid so 16:9 lands at 1536×864, keep PE wh_ratio advisory, and leave Edit on the encode latent from image_1.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-26 10:54:18 -05:00
co-authored by Cursor
parent 2842855c7b
commit 95873744cd
7 changed files with 119 additions and 32 deletions
+10 -1
View File
@@ -40,6 +40,15 @@
"class_type": "TextEncodeQwenImage21",
"_meta": { "title": "Text Encode Qwen Image 2.1" }
},
"16": {
"inputs": {
"width": 1024,
"height": 1024,
"batch_size": 1
},
"class_type": "EmptyLatentImage",
"_meta": { "title": "Qwen 2.1 canvas" }
},
"15": {
"inputs": {
"seed": 1,
@@ -51,7 +60,7 @@
"model": ["3", 0],
"positive": ["9", 0],
"negative": ["9", 1],
"latent_image": ["9", 2]
"latent_image": ["16", 0]
},
"class_type": "KSampler",
"_meta": { "title": "KSampler" }
+10 -13
View File
@@ -14,7 +14,7 @@ import qwen21PeT2iTemplate from '../../assets/studio2_qwen21_pe_t2i.json'
import qwen21PeEditTemplate from '../../assets/studio2_qwen21_pe_edit.json';
import { nativeVideoGraph, attachHeroReference, applyResolvedImageSize } from '~/shared/studio2/graphs.mjs';
import { compilePrompt, scopedFile } from '~/shared/studio2/contracts.mjs';
import { resolveQwen21Size } from '~/shared/studio2/input.mjs';
import { resolveQwen21Size } from '~/shared/studio2/qwen21-size.mjs';
import { createJob, restoreJob, getJob, emitJob, type Job } from '../jobs';
import { markStudioLive, onLiveVideoSettled, type StudioJob } from '../studioQueue';
import { readRecord, saveRecord, studio2Root, records } from './store';
@@ -252,41 +252,38 @@ async function prepareGraph(r: any) {
}
graph['9'].inputs.prompt = prompt
graph['9'].inputs.negative_prompt = stylePrompt(q.imageStyles, true)
// Official edit: sampler latent comes from TextEncode (sized from image_1).
// Do not inject EmptyLatentImage — a mismatched empty canvas shifts the edit.
graph['9'].inputs.resolution = 1024
if (s.aspect && s.aspect !== 'auto') {
graph['16'] = {
inputs: { width: s.width, height: s.height, batch_size: 1 },
class_type: 'EmptyLatentImage',
_meta: { title: 'Qwen edit canvas' }
}
graph['15'].inputs.latent_image = ['16', 0]
}
graph['15'].inputs.seed = s.seed
graph['15'].inputs.steps = s.steps || 25
graph['15'].inputs.cfg = s.cfg ?? 1
graph['15'].inputs.sampler_name = 'euler'
graph['15'].inputs.scheduler = 'simple'
graph['21'].inputs.filename_prefix = prefix + '/image'
r.sampleLatent = s.aspect && s.aspect !== 'auto' ? 'qwen21 empty latent' : 'qwen21 edit latent'
r.sampleLatent = 'qwen21 edit latent'
r.sampleDenoise = null
r.heroReferenceAttached = false
r.graphId = 'studio2_qwen21_edit.json'
} else {
// Bench aspect is law for Generate. PE wh_ratio is advisory only (never sizes the canvas).
const size = resolveQwen21Size(s.aspect)
s.width = size.width
s.height = size.height
graph = structuredClone(qwen21Template)
graph['9'].inputs.prompt = q.compiledPrompt
graph['9'].inputs.negative_prompt = stylePrompt(q.imageStyles, true)
// TextEncodeQwenImage21 builds the 64-ch empty latent from resolution (square T2I).
graph['9'].inputs.resolution = Math.max(size.width, size.height)
// TextEncode conditioning only — EmptyLatentImage (node 16) owns canvas size, matching the official T2I template.
graph['9'].inputs.resolution = 1024
graph['16'].inputs.width = size.width
graph['16'].inputs.height = size.height
graph['15'].inputs.seed = s.seed
graph['15'].inputs.steps = s.steps || 25
graph['15'].inputs.cfg = s.cfg ?? 1
graph['15'].inputs.sampler_name = 'euler'
graph['15'].inputs.scheduler = 'simple'
graph['21'].inputs.filename_prefix = prefix + '/image'
r.sampleLatent = 'qwen21 textencode latent'
r.sampleLatent = 'qwen21 empty latent'
r.sampleDenoise = null
r.heroReferenceAttached = false
r.graphId = 'studio2_qwen21_t2i.json'