Recursos Avançados

Recursos avançados e capacidades do Qwen Image Edit

Processamento Assíncrono

Webhooks para Processamento em Background

import express from 'express';
import { QwenImageEdit } from 'qwen-image-edit';

const app = express();
app.use(express.json());

const editor = new QwenImageEdit({
  apiKey: process.env.QWEN_API_KEY,
  webhookUrl: 'https://meuapp.com/webhook/qwen',
  webhookSecret: process.env.WEBHOOK_SECRET
});

// ✅ Iniciar processamento assíncrono
app.post('/edit-async', async (req, res) => {
  try {
    const { imagem, prompt, callbackUrl } = req.body;
    
    const job = await editor.editTextAsync({
      imagem,
      prompt,
      metadata: {
        userId: req.user.id,
        callbackUrl
      }
    });
    
    res.json({
      jobId: job.id,
      status: 'processing',
      estimatedTime: job.estimatedTime
    });
    
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// ✅ Receber resultado via webhook
app.post('/webhook/qwen', async (req, res) => {
  try {
    // Verificar assinatura do webhook
    const signature = req.headers['x-qwen-signature'];
    const isValid = editor.verifyWebhookSignature(req.body, signature);
    
    if (!isValid) {
      return res.status(401).json({ error: 'Assinatura inválida' });
    }
    
    const { jobId, status, resultado, metadata } = req.body;
    
    if (status === 'completed') {
      // Processar resultado
      await processarResultado(jobId, resultado, metadata);
      
      // Notificar usuário se callback URL fornecida
      if (metadata.callbackUrl) {
        await notificarUsuario(metadata.callbackUrl, {
          jobId,
          status: 'completed',
          imageUrl: resultado.imageUrl
        });
      }
    } else if (status === 'failed') {
      console.error(`Job ${jobId} falhou:`, req.body.error);
    }
    
    res.json({ received: true });
    
  } catch (error) {
    console.error('Erro no webhook:', error);
    res.status(500).json({ error: 'Erro interno' });
  }
});

async function processarResultado(jobId, resultado, metadata) {
  // Salvar resultado no banco de dados
  await database.jobs.update(jobId, {
    status: 'completed',
    resultUrl: resultado.imageUrl,
    creditsUsed: resultado.creditos,
    completedAt: new Date()
  });
  
  console.log(`Job ${jobId} concluído para usuário ${metadata.userId}`);
}

async function notificarUsuario(callbackUrl, dados) {
  try {
    await fetch(callbackUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(dados)
    });
  } catch (error) {
    console.error('Erro ao notificar usuário:', error);
  }
}

Rastreamento de Jobs

class JobTracker {
  constructor(editor) {
    this.editor = editor;
    this.jobs = new Map();
    this.callbacks = new Map();
  }
  
  async criarJob(opcoes, callback) {
    const job = await this.editor.editTextAsync(opcoes);
    
    this.jobs.set(job.id, {
      id: job.id,
      status: 'processing',
      createdAt: new Date(),
      opcoes
    });
    
    if (callback) {
      this.callbacks.set(job.id, callback);
    }
    
    // Iniciar polling para verificar status
    this.iniciarPolling(job.id);
    
    return job;
  }
  
  async iniciarPolling(jobId) {
    const intervalo = setInterval(async () => {
      try {
        const status = await this.editor.getJobStatus(jobId);
        
        this.jobs.set(jobId, {
          ...this.jobs.get(jobId),
          status: status.status,
          progress: status.progress
        });
        
        if (status.status === 'completed' || status.status === 'failed') {
          clearInterval(intervalo);
          
          const callback = this.callbacks.get(jobId);
          if (callback) {
            callback(status);
            this.callbacks.delete(jobId);
          }
        }
        
      } catch (error) {
        console.error(`Erro ao verificar job ${jobId}:`, error);
        clearInterval(intervalo);
      }
    }, 5000); // Verificar a cada 5 segundos
  }
  
  obterStatus(jobId) {
    return this.jobs.get(jobId);
  }
  
  listarJobs(status = null) {
    const jobs = Array.from(this.jobs.values());
    return status ? jobs.filter(job => job.status === status) : jobs;
  }
}

const jobTracker = new JobTracker(editor);

// Usar o tracker
const job = await jobTracker.criarJob({
  imagem: './produto.jpg',
  prompt: 'Alterar cor do produto para azul'
}, (resultado) => {
  console.log('Job concluído:', resultado);
});

console.log('Job criado:', job.id);

Processamento em Lote Otimizado

Controle de Concorrência

import pLimit from 'p-limit';
import pRetry from 'p-retry';

class BatchProcessor {
  constructor(editor, opcoes = {}) {
    this.editor = editor;
    this.concorrencia = opcoes.concorrencia || 3;
    this.tentativas = opcoes.tentativas || 3;
    this.delayRetry = opcoes.delayRetry || 1000;
    
    this.limit = pLimit(this.concorrencia);
    this.estatisticas = {
      total: 0,
      processados: 0,
      sucessos: 0,
      falhas: 0,
      inicioProcessamento: null
    };
  }
  
  async processarLote(itens, callback = null) {
    this.estatisticas.total = itens.length;
    this.estatisticas.inicioProcessamento = new Date();
    
    console.log(`🚀 Iniciando processamento de ${itens.length} itens com concorrência ${this.concorrencia}`);
    
    const resultados = await Promise.allSettled(
      itens.map((item, index) => 
        this.limit(() => this.processarItem(item, index, callback))
      )
    );
    
    // Compilar estatísticas finais
    const sucessos = resultados.filter(r => r.status === 'fulfilled');
    const falhas = resultados.filter(r => r.status === 'rejected');
    
    this.estatisticas.sucessos = sucessos.length;
    this.estatisticas.falhas = falhas.length;
    
    const duracao = Date.now() - this.estatisticas.inicioProcessamento.getTime();
    
    console.log(`✅ Processamento concluído em ${duracao}ms`);
    console.log(`📊 Sucessos: ${sucessos.length}, Falhas: ${falhas.length}`);
    
    return {
      sucessos: sucessos.map(r => r.value),
      falhas: falhas.map(r => ({ error: r.reason, item: r.item })),
      estatisticas: this.estatisticas
    };
  }
  
  async processarItem(item, index, callback) {
    return pRetry(async () => {
      try {
        console.log(`📝 Processando item ${index + 1}/${this.estatisticas.total}`);
        
        const resultado = await this.editor.editText({
          imagem: item.imagem,
          prompt: item.prompt
        });
        
        this.estatisticas.processados++;
        
        if (callback) {
          callback({
            index,
            item,
            resultado,
            status: 'success'
          });
        }
        
        return { item, resultado, index };
        
      } catch (error) {
        console.error(`❌ Erro no item ${index + 1}:`, error.message);
        
        if (callback) {
          callback({
            index,
            item,
            error,
            status: 'error'
          });
        }
        
        throw error;
      }
    }, {
      retries: this.tentativas,
      minTimeout: this.delayRetry,
      onFailedAttempt: (error) => {
        console.log(`🔄 Tentativa ${error.attemptNumber} falhou para item ${index + 1}. Tentando novamente...`);
      }
    });
  }
  
  obterProgresso() {
    return {
      total: this.estatisticas.total,
      processados: this.estatisticas.processados,
      porcentagem: this.estatisticas.total > 0 ? 
        (this.estatisticas.processados / this.estatisticas.total * 100).toFixed(1) : 0
    };
  }
}

// Exemplo de uso
const processor = new BatchProcessor(editor, {
  concorrencia: 5,
  tentativas: 3,
  delayRetry: 2000
});

const itens = [
  { imagem: './img1.jpg', prompt: 'Adicionar logo da empresa' },
  { imagem: './img2.jpg', prompt: 'Alterar cor de fundo para branco' },
  { imagem: './img3.jpg', prompt: 'Remover marca d\'água' }
];

const resultado = await processor.processarLote(itens, (progresso) => {
  console.log(`Progresso: ${progresso.status} - Item ${progresso.index + 1}`);
});

console.log('Resultado final:', resultado);

Processamento Paralelo Inteligente

Balanceamento de Carga

import pLimit from 'p-limit';
import pRetry from 'p-retry';

class IntelligentProcessor {
  constructor(editores, opcoes = {}) {
    this.editores = editores; // Array de instâncias QwenImageEdit
    this.opcoes = {
      concorrenciaPorEditor: opcoes.concorrenciaPorEditor || 2,
      tentativas: opcoes.tentativas || 3,
      timeoutRequest: opcoes.timeoutRequest || 60000,
      ...opcoes
    };
    
    // Criar limitadores para cada editor
    this.limitadores = this.editores.map(editor => ({
      editor,
      limit: pLimit(this.opcoes.concorrenciaPorEditor),
      estatisticas: {
        requisicoes: 0,
        sucessos: 0,
        falhas: 0,
        tempoMedio: 0
      }
    }));
    
    this.filaProcessamento = [];
    this.processandoFila = false;
  }
  
  async editText(opcoes) {
    return new Promise((resolve, reject) => {
      this.filaProcessamento.push({
        opcoes,
        resolve,
        reject,
        timestamp: Date.now()
      });
      
      this.processarFila();
    });
  }
  
  async processarFila() {
    if (this.processandoFila || this.filaProcessamento.length === 0) {
      return;
    }
    
    this.processandoFila = true;
    
    while (this.filaProcessamento.length > 0) {
      const item = this.filaProcessamento.shift();
      
      // Selecionar melhor editor baseado em estatísticas
      const melhorEditor = this.selecionarMelhorEditor();
      
      // Processar com o editor selecionado
      melhorEditor.limit(async () => {
        try {
          const startTime = Date.now();
          
          const resultado = await pRetry(async () => {
            return melhorEditor.editor.editText(item.opcoes);
          }, {
            retries: this.opcoes.tentativas,
            minTimeout: 1000
          });
          
          const duracao = Date.now() - startTime;
          
          // Atualizar estatísticas
          melhorEditor.estatisticas.requisicoes++;
          melhorEditor.estatisticas.sucessos++;
          melhorEditor.estatisticas.tempoMedio = 
            (melhorEditor.estatisticas.tempoMedio + duracao) / 2;
          
          item.resolve(resultado);
          
        } catch (error) {
          melhorEditor.estatisticas.requisicoes++;
          melhorEditor.estatisticas.falhas++;
          
          item.reject(error);
        }
      });
    }
    
    this.processandoFila = false;
  }
  
  selecionarMelhorEditor() {
    // Calcular score para cada editor
    const scores = this.limitadores.map(limitador => {
      const stats = limitador.estatisticas;
      
      // Fatores: taxa de sucesso, tempo médio, carga atual
      const taxaSucesso = stats.requisicoes > 0 ? 
        stats.sucessos / stats.requisicoes : 1;
      
      const fatorTempo = stats.tempoMedio > 0 ? 
        1 / (stats.tempoMedio / 1000) : 1;
      
      const cargaAtual = limitador.limit.activeCount / this.opcoes.concorrenciaPorEditor;
      const fatorCarga = 1 - cargaAtual;
      
      return {
        limitador,
        score: taxaSucesso * fatorTempo * fatorCarga
      };
    });
    
    // Retornar editor com melhor score
    return scores.reduce((melhor, atual) => 
      atual.score > melhor.score ? atual : melhor
    ).limitador;
  }
  
  obterEstatisticas() {
    return this.limitadores.map((limitador, index) => ({
      editorIndex: index,
      ...limitador.estatisticas,
      cargaAtual: limitador.limit.activeCount,
      filaAtual: limitador.limit.pendingCount
    }));
  }
}

// Configurar múltiplos editores
const editores = [
  new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY_1, region: 'us-east-1' }),
  new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY_2, region: 'us-west-1' }),
  new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY_3, region: 'eu-west-1' })
];

const processor = new IntelligentProcessor(editores, {
  concorrenciaPorEditor: 3,
  tentativas: 2
});

// Usar como um editor normal
const resultado = await processor.editText({
  imagem: './imagem.jpg',
  prompt: 'Editar texto'
});

Análise Profunda de Imagens

Detecção Avançada de Conteúdo

class AnaliseAvancada {
  constructor(editor) {
    this.editor = editor;
  }
  
  async analisarCompleta(imagem) {
    const analises = await Promise.all([
      this.analisarTexto(imagem),
      this.analisarObjetos(imagem),
      this.analisarFaces(imagem),
      this.analisarCores(imagem),
      this.analisarEstilo(imagem),
      this.analisarQualidade(imagem)
    ]);
    
    return {
      texto: analises[0],
      objetos: analises[1],
      faces: analises[2],
      cores: analises[3],
      estilo: analises[4],
      qualidade: analises[5],
      resumo: this.gerarResumo(analises)
    };
  }
  
  async analisarTexto(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['texto'],
      opcoes: {
        idiomas: ['pt', 'en', 'es'],
        incluirConfianca: true,
        incluirPosicao: true
      }
    });
    
    return {
      textos: resultado.texto,
      estatisticas: {
        totalTextos: resultado.texto.length,
        idiomasPredominantes: this.analisarIdiomas(resultado.texto),
        confiancaMedia: this.calcularConfiancaMedia(resultado.texto)
      }
    };
  }
  
  async analisarObjetos(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['objetos'],
      opcoes: {
        incluirConfianca: true,
        incluirBoundingBox: true,
        categorias: ['pessoas', 'veiculos', 'animais', 'objetos']
      }
    });
    
    return {
      objetos: resultado.objetos,
      estatisticas: {
        totalObjetos: resultado.objetos.length,
        categorias: this.agruparPorCategoria(resultado.objetos),
        densidadeObjetos: this.calcularDensidade(resultado.objetos)
      }
    };
  }
  
  async analisarFaces(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['faces'],
      opcoes: {
        incluirEmocoes: true,
        incluirIdade: true,
        incluirGenero: true,
        incluirPosicao: true
      }
    });
    
    return {
      faces: resultado.faces,
      estatisticas: {
        totalFaces: resultado.faces.length,
        emocoesPredominantes: this.analisarEmocoes(resultado.faces),
        faixaEtaria: this.analisarIdades(resultado.faces)
      }
    };
  }
  
  async analisarCores(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['cores'],
      opcoes: {
        numeroCores: 10,
        incluirPorcentagem: true,
        incluirHSL: true,
        incluirRGB: true
      }
    });
    
    return {
      cores: resultado.cores,
      paleta: this.gerarPaleta(resultado.cores),
      estatisticas: {
        corPredominante: resultado.cores[0],
        saturacaoMedia: this.calcularSaturacaoMedia(resultado.cores),
        brilhoMedio: this.calcularBrilhoMedio(resultado.cores)
      }
    };
  }
  
  async analisarEstilo(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['estilo'],
      opcoes: {
        categorias: ['fotografia', 'ilustracao', 'arte', 'design'],
        incluirConfianca: true
      }
    });
    
    return {
      estilo: resultado.estilo,
      categoria: resultado.estilo.categoria,
      confianca: resultado.estilo.confianca,
      caracteristicas: resultado.estilo.caracteristicas
    };
  }
  
  async analisarQualidade(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['qualidade'],
      opcoes: {
        metricas: ['nitidez', 'ruido', 'exposicao', 'contraste'],
        incluirSugestoes: true
      }
    });
    
    return {
      qualidade: resultado.qualidade,
      pontuacao: resultado.qualidade.pontuacaoGeral,
      problemas: resultado.qualidade.problemas,
      sugestoes: resultado.qualidade.sugestoes
    };
  }
  
  gerarResumo(analises) {
    const [texto, objetos, faces, cores, estilo, qualidade] = analises;
    
    return {
      tipo: this.determinarTipoImagem(analises),
      complexidade: this.calcularComplexidade(analises),
      adequacaoEdicao: this.avaliarAdequacaoEdicao(analises),
      sugestoesOtimizacao: this.gerarSugestoesOtimizacao(analises)
    };
  }
  
  determinarTipoImagem(analises) {
    const [texto, objetos, faces] = analises;
    
    if (faces.faces.length > 0) return 'retrato';
    if (texto.textos.length > 5) return 'documento';
    if (objetos.objetos.length > 10) return 'cena_complexa';
    
    return 'geral';
  }
  
  calcularComplexidade(analises) {
    const [texto, objetos, faces, cores] = analises;
    
    let score = 0;
    score += texto.textos.length * 2;
    score += objetos.objetos.length * 1;
    score += faces.faces.length * 3;
    score += cores.cores.length * 0.5;
    
    if (score < 10) return 'baixa';
    if (score < 25) return 'media';
    return 'alta';
  }
  
  avaliarAdequacaoEdicao(analises) {
    const [, , , , , qualidade] = analises;
    
    if (qualidade.pontuacao > 0.8) return 'excelente';
    if (qualidade.pontuacao > 0.6) return 'boa';
    if (qualidade.pontuacao > 0.4) return 'regular';
    return 'ruim';
  }
  
  gerarSugestoesOtimizacao(analises) {
    const sugestoes = [];
    const [, , , , , qualidade] = analises;
    
    if (qualidade.qualidade.nitidez < 0.5) {
      sugestoes.push('Considere aplicar filtro de nitidez antes da edição');
    }
    
    if (qualidade.qualidade.ruido > 0.7) {
      sugestoes.push('Recomenda-se redução de ruído para melhor resultado');
    }
    
    if (qualidade.qualidade.exposicao < 0.3) {
      sugestoes.push('Imagem subexposta - considere ajustar brilho');
    }
    
    return sugestoes;
  }
}

const analisador = new AnaliseAvancada(editor);

// Análise completa
const analise = await analisador.analisarCompleta('./imagem-complexa.jpg');
console.log('Análise completa:', JSON.stringify(analise, null, 2));

Detecção de Conteúdo Sensível

Sistema de Moderação

class ModeracaoConteudo {
  constructor(editor) {
    this.editor = editor;
    this.politicas = {
      violencia: { ativo: true, limite: 0.3 },
      nudez: { ativo: true, limite: 0.2 },
      drogas: { ativo: true, limite: 0.4 },
      linguagemOfensiva: { ativo: true, limite: 0.3 }
    };
  }
  
  async verificarConteudo(imagem) {
    const resultado = await this.editor.analyzeImage({
      imagem,
      detectar: ['conteudo_sensivel'],
      opcoes: {
        categorias: Object.keys(this.politicas),
        incluirConfianca: true,
        incluirDetalhes: true
      }
    });
    
    const violacoes = this.identificarViolacoes(resultado.conteudoSensivel);
    
    return {
      aprovado: violacoes.length === 0,
      violacoes,
      pontuacoes: resultado.conteudoSensivel,
      recomendacoes: this.gerarRecomendacoes(violacoes)
    };
  }
  
  identificarViolacoes(pontuacoes) {
    const violacoes = [];
    
    for (const [categoria, pontuacao] of Object.entries(pontuacoes)) {
      const politica = this.politicas[categoria];
      
      if (politica && politica.ativo && pontuacao.confianca > politica.limite) {
        violacoes.push({
          categoria,
          pontuacao: pontuacao.confianca,
          limite: politica.limite,
          detalhes: pontuacao.detalhes
        });
      }
    }
    
    return violacoes;
  }
  
  gerarRecomendacoes(violacoes) {
    const recomendacoes = [];
    
    for (const violacao of violacoes) {
      switch (violacao.categoria) {
        case 'violencia':
          recomendacoes.push('Remover ou censurar conteúdo violento');
          break;
        case 'nudez':
          recomendacoes.push('Aplicar censura ou remover conteúdo explícito');
          break;
        case 'drogas':
          recomendacoes.push('Remover referências a substâncias ilegais');
          break;
        case 'linguagemOfensiva':
          recomendacoes.push('Censurar ou substituir linguagem ofensiva');
          break;
      }
    }
    
    return recomendacoes;
  }
  
  async editarComModeracao(opcoes) {
    // Verificar conteúdo antes da edição
    const moderacao = await this.verificarConteudo(opcoes.imagem);
    
    if (!moderacao.aprovado) {
      throw new Error(`Conteúdo rejeitado: ${moderacao.violacoes.map(v => v.categoria).join(', ')}`);
    }
    
    // Proceder com edição
    const resultado = await this.editor.editText(opcoes);
    
    // Verificar resultado após edição
    const moderacaoResultado = await this.verificarConteudo(resultado.imagem);
    
    if (!moderacaoResultado.aprovado) {
      console.warn('Resultado da edição contém conteúdo sensível:', moderacaoResultado.violacoes);
    }
    
    return {
      ...resultado,
      moderacao: {
        original: moderacao,
        resultado: moderacaoResultado
      }
    };
  }
}

const moderador = new ModeracaoConteudo(editor);

// Editar com moderação
try {
  const resultado = await moderador.editarComModeracao({
    imagem: './imagem.jpg',
    prompt: 'Adicionar texto motivacional'
  });
  
  console.log('Edição aprovada:', resultado);
} catch (error) {
  console.error('Edição rejeitada:', error.message);
}

Edição Condicional

Edição Baseada em Análise

class EdicaoCondicional {
  constructor(editor) {
    this.editor = editor;
    this.analisador = new AnaliseAvancada(editor);
  }
  
  async editarSeCondicao(imagem, condicoes, edicoes) {
    // Analisar imagem primeiro
    const analise = await this.analisador.analisarCompleta(imagem);
    
    // Verificar condições
    const condicoesAtendidas = this.verificarCondicoes(analise, condicoes);
    
    if (condicoesAtendidas.length === 0) {
      return {
        editado: false,
        motivo: 'Nenhuma condição atendida',
        analise
      };
    }
    
    // Aplicar edições baseadas nas condições atendidas
    let imagemAtual = imagem;
    const edicoesAplicadas = [];
    
    for (const condicao of condicoesAtendidas) {
      const edicao = edicoes[condicao.nome];
      
      if (edicao) {
        console.log(`Aplicando edição para condição: ${condicao.nome}`);
        
        const resultado = await this.editor.editText({
          imagem: imagemAtual,
          prompt: edicao.prompt,
          ...edicao.opcoes
        });
        
        imagemAtual = resultado.imagem;
        edicoesAplicadas.push({
          condicao: condicao.nome,
          edicao: edicao.prompt,
          creditos: resultado.creditos
        });
      }
    }
    
    return {
      editado: true,
      imagemFinal: imagemAtual,
      edicoesAplicadas,
      analise,
      creditosTotal: edicoesAplicadas.reduce((total, e) => total + e.creditos, 0)
    };
  }
  
  verificarCondicoes(analise, condicoes) {
    const atendidas = [];
    
    for (const [nome, condicao] of Object.entries(condicoes)) {
      if (this.avaliarCondicao(analise, condicao)) {
        atendidas.push({ nome, ...condicao });
      }
    }
    
    return atendidas;
  }
  
  avaliarCondicao(analise, condicao) {
    switch (condicao.tipo) {
      case 'tem_texto':
        return analise.texto.textos.length > 0;
        
      case 'tem_faces':
        return analise.faces.faces.length >= (condicao.minimo || 1);
        
      case 'qualidade_baixa':
        return analise.qualidade.pontuacao < (condicao.limite || 0.5);
        
      case 'cor_predominante':
        const corPredominante = analise.cores.cores[0];
        return this.compararCor(corPredominante.rgb, condicao.cor);
        
      case 'tem_objeto':
        return analise.objetos.objetos.some(obj => 
          obj.nome.toLowerCase().includes(condicao.objeto.toLowerCase())
        );
        
      case 'estilo':
        return analise.estilo.categoria === condicao.categoria;
        
      case 'complexidade':
        return analise.resumo.complexidade === condicao.nivel;
        
      default:
        return false;
    }
  }
  
  compararCor(rgb1, rgb2, tolerancia = 50) {
    const distancia = Math.sqrt(
      Math.pow(rgb1.r - rgb2.r, 2) +
      Math.pow(rgb1.g - rgb2.g, 2) +
      Math.pow(rgb1.b - rgb2.b, 2)
    );
    
    return distancia <= tolerancia;
  }
}

// Exemplo de uso
const edicaoCondicional = new EdicaoCondicional(editor);

const condicoes = {
  'melhorar_qualidade': {
    tipo: 'qualidade_baixa',
    limite: 0.6
  },
  'adicionar_logo': {
    tipo: 'tem_objeto',
    objeto: 'produto'
  },
  'ajustar_cores': {
    tipo: 'cor_predominante',
    cor: { r: 255, g: 255, b: 255 } // Branco predominante
  }
};

const edicoes = {
  'melhorar_qualidade': {
    prompt: 'Melhorar nitidez e reduzir ruído da imagem',
    opcoes: { qualidade: 'alta' }
  },
  'adicionar_logo': {
    prompt: 'Adicionar logo da empresa no canto superior direito',
    opcoes: { posicao: 'canto_superior_direito' }
  },
  'ajustar_cores': {
    prompt: 'Ajustar cores para ter mais contraste e vivacidade',
    opcoes: { intensidade: 'media' }
  }
};

const resultado = await edicaoCondicional.editarSeCondicao(
  './produto.jpg',
  condicoes,
  edicoes
);

console.log('Resultado da edição condicional:', resultado);

Continue explorando: Estes recursos avançados permitem criar soluções sofisticadas e escaláveis com Qwen Image Edit. Para implementações específicas, consulte nossa documentação da API ou entre em contato com o suporte.