liuhairui 5 сар өмнө
parent
commit
eee57ac5c0

+ 180 - 84
application/api/controller/WorkOrder.php

@@ -27,34 +27,21 @@ class WorkOrder extends Api
     }
 
 
+
     /**
-     * 图生图功能 - /sdapi/v1/img2img
+     * 图生图功能-单张图片本地测试使用
+     * 接口地址: /sdapi/v1/img2img
      */
     public function imgtowimg()
     {
-        $prompt = $this->request->param('prompt', ''); // 用户传入的提示词
-//        $imgRelPath = 'uploads/operate/ai/Preview/arr/0828004096727.png';
-//        $imgRelPath = 'uploads/operate/ai/Preview/arr/1751019283787.jpg';
-        $imgRelPath = 'uploads/operate/ai/Preview/arr/圣诞主题复古油画圣诞老人和孩子们乘坐红色雪橇在雪地中滑行充满.png';
+        $prompt = $this->request->param('prompt', '将图片不完整部分补充完整');
+        $imgRelPath = 'uploads/operate/ai/Preview/arr/一朵盛开的白色牡丹花为主体采用厚涂技法花心和背景点缀金箔灰银.png';
         $imgPath = ROOT_PATH . 'public/' . $imgRelPath;
-
-        // 校验原图是否存在
+        //原图是否存在
         if (!file_exists($imgPath)) {
             return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
         }
 
-        // -------- 参数调整 -------- //
-        $denoising = 0.2;                           // 降低重绘幅度
-        $steps = 10;                                // 减少迭代步数
-        $cfgScale = 7;
-        $clipSkip = 7;
-        $sampler = 'DPM++ 2M SDE Heun';
-        $modelName = 'realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]';
-        $vaeName = 'anything-v4.5.vae.pt';
-        $seed = 611075477;
-        $targetW = 679;                             // 目标宽度
-        $targetH = 862;                             // 目标高度
-
         // -------- 图像编码 -------- //
         $imgData = file_get_contents($imgPath);
         $base64Img = base64_encode($imgData);
@@ -63,21 +50,24 @@ class WorkOrder extends Api
         // -------- 请求体构建 -------- //
         $postData = json_encode([
             'prompt' => $prompt,
-            'steps' => $steps,
-            'cfg_scale' => $cfgScale,
-            'denoising_strength' => $denoising,
-            'width' => $targetW,
-            'height' => $targetH,
-            'resize_mode' => 0,
-            'sampler_name' => $sampler,
-            'seed' => $seed,
-            'inpaint_full_res' => true,            // 关闭高分辨率重绘
-            'inpainting_fill' => 1,
-            'init_images' => [$initImage],
+            'steps' => 30,                       // 步数
+            'cfg_scale' => 7,                    // CFG 强度
+            'denoising_strength' => 0.2,        // 重绘强度
+            'width' => 679,                      // 图像宽度
+            'height' => 862,                     // 图像高度
+            'resize_mode' => 1,                 // 保留原图比例并裁剪
+            'inpaint_full_res' => true,         // 使用原图分辨率
+            'inpaint_full_res_padding' => 64,   // 边缘补全像素
+            'mask_blur' => 4,                   // 蒙版柔化
+            'inpainting_fill' => 3,             // 自动填充内容(不是黑色)
+            'sampler_name' => 'DPM++ 2M SDE',   // 采样器
+            'scheduler' => 'Exponential',       // ✅ 调度类型(补充字段)
+            'seed' => 3689437019,               // 固定种子(确保结果可复现)
+            'init_images' => [$initImage],      // 原图 base64
             'override_settings' => [
-                'sd_model_checkpoint' => $modelName,
-                'sd_vae' => $vaeName,
-                'CLIP_stop_at_last_layers' => $clipSkip
+                'sd_model_checkpoint' => 'AbyssOrangeMix2_sfw', // 模型名
+                'sd_vae' => "Automatic",
+                'CLIP_stop_at_last_layers' => 2
             ],
             'override_settings_restore_afterwards' => true
         ]);
@@ -97,10 +87,7 @@ class WorkOrder extends Api
         $error = curl_error($ch);
         curl_close($ch);
 
-        if ($error) {
-            return json(['code' => 1, 'msg' => '请求失败:' . $error]);
-        }
-
+        if ($error) {return json(['code' => 1, 'msg' => '请求失败:' . $error]);}
         $data = json_decode($response, true);
         if (!isset($data['images'][0])) {
             return json(['code' => 1, 'msg' => '接口未返回图像数据']);
@@ -127,84 +114,193 @@ class WorkOrder extends Api
         ]);
     }
 
+
     /**
-     * 后期图像处理
-     * /sdapi/v1/extra-single-image
+     * 后期图像处理-单张图片高清放大处理
+     * 接口地址: /sdapi/v1/extra-single-image
      */
     public function extra_image()
     {
-        $imgRelPath = 'uploads/img2img/0828004096727-1.png'; // 图生图结果
-        $imgPath = ROOT_PATH . 'public/' . $imgRelPath;
+        // 配置参数
+        $config = [
+            'input_dir' => 'uploads/operate/ai/Preview/arr/',
+            'output_dir' => 'uploads/extra_image/',
+            'api_url' => 'http://20.0.17.233:45001/sdapi/v1/extra-single-image',
+            'timeout' => 120, // 增加超时时间,高清处理可能耗时较长
+            'upscale_params' => [
+                'resize_mode' => 0,
+                'show_extras_results' => true,
+                'gfpgan_visibility' => 0, // 人脸修复关闭
+                'codeformer_visibility' => 0, // 人脸修复关闭
+                'codeformer_weight' => 0,
+                'upscaling_resize' => 2.45, // 放大倍数
+                'upscaling_crop' => true,
+                'upscaler_1' => 'R-ESRGAN 4x+ Anime6B', // 主放大模型
+                'upscaler_2' => 'None', // 不使用第二放大器
+                'extras_upscaler_2_visibility' => 0,
+                'upscale_first' => false,
+            ]
+        ];
+
+        // 输入文件处理
+        $imgRelPath = '图案的整体色调是柔和的蓝色和灰色形成温馨而宁静的视觉效果花卉.png';
+        $imgPath = ROOT_PATH . 'public/' . $config['input_dir'] . $imgRelPath;
 
         if (!file_exists($imgPath)) {
             return json(['code' => 1, 'msg' => '原图不存在:' . $imgRelPath]);
         }
 
-        $imgData = file_get_contents($imgPath);
-        $base64Img = base64_encode($imgData);
-
-        $postData = json_encode([
-            'resize_mode' => 0,
-            'show_extras_results' => true,
-            'gfpgan_visibility' => 0,
-            'codeformer_visibility' => 0,
-            'codeformer_weight' => 0,
-            'upscaling_resize' => 2.45,
-            'upscaling_crop' => true,
-            'upscaler_1' => 'R-ESRGAN 4x+ Anime6B',
-            'upscaler_2' => 'None',
-            'extras_upscaler_2_visibility' => 0,
-            'upscale_first' => false,
-            'image' => $base64Img
-        ]);
+        // 读取并编码图片
+        try {
+            $imgData = file_get_contents($imgPath);
+            if ($imgData === false) {
+                throw new Exception('无法读取图片文件');
+            }
+            $base64Img = base64_encode($imgData);
+        } catch (Exception $e) {
+            return json(['code' => 1, 'msg' => '图片处理失败:' . $e->getMessage()]);
+        }
 
-        $apiUrl = "http://20.0.17.233:45001/sdapi/v1/extra-single-image";
-        $headers = ['Content-Type: application/json'];
+        // 准备API请求数据
+        $postData = array_merge($config['upscale_params'], ['image' => $base64Img]);
+        $jsonData = json_encode($postData);
+        if ($jsonData === false) {
+            return json(['code' => 1, 'msg' => 'JSON编码失败']);
+        }
 
+        // 调用API进行高清放大
         $ch = curl_init();
-        curl_setopt($ch, CURLOPT_URL, $apiUrl);
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        curl_setopt($ch, CURLOPT_POST, true);
-        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
-        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
-        curl_setopt($ch, CURLOPT_TIMEOUT, 90);
+        curl_setopt_array($ch, [
+            CURLOPT_URL => $config['api_url'],
+            CURLOPT_RETURNTRANSFER => true,
+            CURLOPT_POST => true,
+            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
+            CURLOPT_POSTFIELDS => $jsonData,
+            CURLOPT_TIMEOUT => $config['timeout'],
+            CURLOPT_CONNECTTIMEOUT => 30,
+        ]);
+
         $response = curl_exec($ch);
         $error = curl_error($ch);
+        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
         curl_close($ch);
 
         if ($error) {
-            return json(['code' => 1, 'msg' => '请求失败:' . $error]);
+            return json(['code' => 1, 'msg' => 'API请求失败:' . $error]);
+        }
+
+        if ($httpCode !== 200) {
+            return json(['code' => 1, 'msg' => 'API返回错误状态码:' . $httpCode]);
         }
 
         $data = json_decode($response, true);
-        if (!isset($data['image'])) {
-            return json(['code' => 1, 'msg' => '接口未返回图像数据']);
+        if (json_last_error() !== JSON_ERROR_NONE) {
+            return json(['code' => 1, 'msg' => 'API返回数据解析失败']);
         }
 
-        // 保存:原图基础名 + -2
-        $resultImg = base64_decode($data['image']);
-        $saveDir = ROOT_PATH . 'public/uploads/extra_image/';
-        if (!is_dir($saveDir)) {
-            mkdir($saveDir, 0755, true);
+        if (!isset($data['image']) || empty($data['image'])) {
+            return json(['code' => 1, 'msg' => '接口未返回有效的图像数据']);
         }
 
-        $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
-        $fileName = $originalBaseName . '-2.png';
-        $savePath = $saveDir . $fileName;
-        file_put_contents($savePath, $resultImg);
+        // 保存处理后的图片
+        try {
+            $resultImg = base64_decode($data['image']);
+            if ($resultImg === false) {
+                throw new Exception('Base64解码失败');
+            }
+
+            $saveDir = ROOT_PATH . 'public/' . $config['output_dir'];
+            if (!is_dir($saveDir) && !mkdir($saveDir, 0755, true)) {
+                throw new Exception('无法创建输出目录');
+            }
+
+            $originalBaseName = pathinfo($imgRelPath, PATHINFO_FILENAME);
+            $fileName = $originalBaseName . '-hd.png'; // 使用-hd后缀更明确
+            $savePath = $saveDir . $fileName;
+
+            if (file_put_contents($savePath, $resultImg) === false) {
+                throw new Exception('无法保存处理后的图片');
+            }
+
+            // 返回成功响应
+            return json([
+                'code' => 0,
+                'msg' => '图像高清放大处理成功',
+                'data' => [
+                    'url' => '/' . $config['output_dir'] . $fileName,
+                    'original_size' => filesize($imgPath),
+                    'processed_size' => filesize($savePath),
+                    'resolution' => getimagesize($savePath), // 返回新图片的分辨率
+                ]
+            ]);
+
+        } catch (Exception $e) {
+            return json(['code' => 1, 'msg' => '保存结果失败:' . $e->getMessage()]);
+        }
+    }
+
+
+
+
+
+    /**
+     * 获取 SD 模型列表
+     * 接口地址: /sdapi/v1/sd-models
+     */
+    public function sd_models() {
+        $url = "http://20.0.17.233:45001/sdapi/v1/sd-models";
+
+        // 初始化 cURL
+        $ch = curl_init();
+
+        // 设置请求参数
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, [
+            'Content-Type: application/json',
+            'Accept: application/json',
+        ]);
 
+        // 发送请求
+        $response = curl_exec($ch);
+
+        // 错误处理
+        if (curl_errno($ch)) {
+            curl_close($ch);
+            return json([
+                'code' => 1,
+                'msg'  => '请求失败: ' . curl_error($ch),
+                'data' => [],
+                'count' => 0
+            ]);
+        }
+
+        curl_close($ch);
+
+        // 解析 JSON 响应
+        $result = json_decode($response, true);
+
+        // 判断返回数据是否有效
+        if (!is_array($result)) {
+            return json([
+                'code' => 1,
+                'msg'  => '数据解析失败',
+                'data' => [],
+                'count' => 0
+            ]);
+        }
+
+        // 正常返回
         return json([
             'code' => 0,
-            'msg' => '图像后处理成功',
-            'data' => [
-                'url' => '/uploads/extra_image/' . $fileName
-            ]
+            'msg'  => '查询成功',
+            'data' => $result,
+            'count' => count($result)
         ]);
     }
 
 
-
-
     /**
      * 查询队列列表
      * 统计文件对应的队列情况

+ 3 - 0
application/job/ImageArrJob.php

@@ -66,6 +66,9 @@ class ImageArrJob
                 case '图生图':
                     Queue::push('app\job\ImageToImageJob', array_merge($value, ['chain_next' => $chain_next]), 'imgtoimg');
                     break;
+                case '高清放大':
+                    Queue::push('app\job\ImageToSingleJob', array_merge($value, ['chain_next' => $chain_next]), 'single');
+                    break;
                 default:
                     \think\Log::warning("未识别的任务类型:" . json_encode($value, JSON_UNESCAPED_UNICODE));
                     break;

+ 0 - 1
application/job/ImageToImageJob.php

@@ -282,7 +282,6 @@ class ImageToImageJob{
         $savePath = $targetDir . $finalFileName;
         file_put_contents($savePath, base64_decode($res['data']['url']));
 
-        // ✅ 修正:数据库中记录相对路径一致
         Db::name('text_to_image')->where('id', $record['id'])->update([
             'imgtoimg_url' => $outputDirRaw . '/' . $dateDir . 'newimg_679x862/' . $finalFileName,
             'status_name' => '图生图',

+ 193 - 0
application/job/ImageToSingleJob.php

@@ -0,0 +1,193 @@
+<?php
+namespace app\job;
+use app\service\AIGatewayService;
+use think\Db;
+use think\queue\Job;
+use think\Queue;
+
+class ImageToSingleJob{
+
+    public function fire(Job $job, $data)
+    {
+
+        $logId = $data['log_id'] ?? null;
+
+        try {
+            // 任务类型校验(必须是图生图)
+            if (!isset($data['type']) || $data['type'] !== '高清放大') {
+                $job->delete();
+                return;
+            }
+
+            $startTime = date('Y-m-d H:i:s');
+            echo "━━━━━━━━━━ ▶ 高清放大任务开始处理━━━━━━━━━━\n";
+            echo "处理时间:{$startTime}\n";
+
+            // 更新日志状态:处理中
+            if ($logId) {
+                Db::name('image_task_log')->where('id', $logId)->update([
+                    'status' => 1,
+                    'log' => '高清放大处理中',
+                    'update_time' => $startTime
+                ]);
+            }
+
+            //拼接原图文件路径 + 图片名称
+            $old_image_url = rtrim($data['sourceDir'], '/') . '/' . ltrim($data['file_name'], '/');
+
+            $list = Db::name("text_to_image")
+                ->where('old_image_url', $old_image_url)
+                ->where('img_name', '<>', '')
+                ->where('status', 1)
+                ->select();
+
+            if (!empty($list)) {
+                $total = count($list);
+                echo "📊 共需处理:{$total} 条记录\n\n";
+
+                foreach ($list as $index => $row) {
+                    $currentIndex = $index + 1;
+                    $begin = date('Y-m-d H:i:s');
+                    echo "处理时间:{$begin}\n";
+                    echo "👉 正在处理第 {$currentIndex} 条,ID: {$row['id']}\n";
+
+                    // 调用生成图像方法
+                    $result = $this->ImageToImage(
+                        $data["file_name"],
+                        $data["outputDir"],
+                        $row["new_image_url"],
+                        $row["img_name"],
+                        679,
+                        862
+                    );
+
+                    $resultText = ($result === true || $result === 1 || $result === '成功') ? '成功' : '失败或无返回';
+                    echo "✅ 处理结果:{$resultText}\n";
+
+                    $end = date('Y-m-d H:i:s');
+                    echo "完成时间:{$end}\n";
+                    echo "Processed: " . static::class . "\n";
+                    echo "高清放大已处理完成\n\n";
+                }
+
+                // 更新日志状态:成功
+                if ($logId) {
+                    Db::name('image_task_log')->where('id', $logId)->update([
+                        'status' => 2,
+                        'log' => '高清放大处理成功',
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+                }
+
+                echo date('Y-m-d H:i:s') . " 高清放大任务全部完成\n";
+            } else {
+
+                echo "未找到可处理的数据,跳过执行\n";
+                if ($logId) {
+                    Db::name('image_task_log')->where('id', $logId)->update([
+                        'status' => 2,
+                        'log' => '无数据可处理,已跳过'.$old_image_url,
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+                }
+            }
+
+            // 如果还有链式任务,继续推送
+            if (!empty($data['chain_next'])) {
+                $nextType = array_shift($data['chain_next']);
+                $data['type'] = $nextType;
+
+                Queue::push('app\job\ImageArrJob', [
+                    'task_id' => $data['task_id'],
+                    'data' => [$data]
+                ], 'arrimage');
+            }
+
+            $job->delete();
+
+        }  catch (\Exception $e) {
+            //异常处理,记录失败日志
+            echo "错误信息: " . $e->getMessage() . "\n";
+            echo "文件: " . $e->getFile() . "\n";
+            echo "行号: " . $e->getLine() . "\n";
+
+            // 删除当前任务
+            $job->delete();
+        }
+    }
+
+    /**
+     * 失败回调(可用于后续通知或重试机制)
+     */
+    public function failed($data)
+    {
+        echo "ImageJob failed: " . json_encode($data);
+    }
+
+
+    public function ImageToImage($fileName, $outputDirRaw, $new_image_url, $width, $height)
+    {
+        // 统一路径分隔符
+        $rootPath = str_replace('\\', '/', ROOT_PATH);
+
+        // 输出目录,如:ROOT/public/uploads/operate/ai/dall-e/
+        $outputDir = rtrim($rootPath . 'public/' . $outputDirRaw, '/') . '/';
+
+        // 当前日期目录,如:2025-06-16/
+        $dateDir = date('Y-m-d') . '/';
+
+        // 完整基本路径,如:ROOT/public/uploads/operate/ai/dall-e/hua/2025-06-16/
+        $fullBaseDir = $outputDir . $dateDir;
+
+        // 创建输出目录,包括原图目录、目录、自定义尺寸目录
+        foreach ([$fullBaseDir, $fullBaseDir . 'newimg_679x862/', $fullBaseDir . "{$width}x{$height}/"] as $dir) {
+            if (!is_dir($dir)) {
+                mkdir($dir, 0755, true);
+            }
+        }
+
+        // 从数据库中查询原图记录
+        $record = Db::name('text_to_image')
+            ->where('old_image_url', 'like', "%{$fileName}")
+            ->order('id desc')
+            ->find();
+
+        if (!$record) {
+            return json([
+                'code' => 1,
+                'msg' => '没有找到匹配的图像记录'
+            ]);
+        }
+
+        // 调用图生图 API
+        $ai = new AIGatewayService();
+        $res = $ai->imgtogqGptApi($new_image_url);
+
+        // 检查返回结果
+        if (!isset($res['code']) || $res['code'] !== 0) {
+            return json([
+                'code' => 1,
+                'msg' => $res['msg'] ?? '图像高清放大生成失败'
+            ]);
+        }
+
+        // 解码图像 base64 数据
+        $originalBaseName = pathinfo($new_image_url, PATHINFO_FILENAME);
+        $finalFileName = $originalBaseName . '.png';
+
+        // 保存到 子目录
+        $targetDir = $fullBaseDir . 'newimg_679x862/';
+        $savePath = $targetDir . $finalFileName;
+        file_put_contents($savePath, base64_decode($res['data']['url']));
+
+        Db::name('text_to_image')->where('id', $record['id'])->update([
+            'imgtoimg_url' => $outputDirRaw . '/' . $dateDir . 'newimg_679x862/' . $finalFileName,
+            'status_name' => '高清放大',
+            'error_msg' => '',
+            'update_time' => date('Y-m-d H:i:s')
+        ]);
+
+        return '成功';
+    }
+
+}

+ 121 - 0
application/service/AIGatewayService.php

@@ -257,6 +257,127 @@ class AIGatewayService{
         ];
     }
 
+
+    /**
+     * 图片高清放大
+     */
+    /**
+     * 图片高清放大
+     * @param string $imageRelPath 原图相对路径(相对 public)
+     * @param array $options 可选参数,可覆盖默认放大配置
+     * @return array
+     */
+    public function imgtogqGptApi($imageRelPath, $options = [])
+    {
+        // 构造图片路径
+        $imgPath = ROOT_PATH . 'public/' . $imageRelPath;
+
+        if (!file_exists($imgPath)) {
+            return ['code' => 1, 'msg' => '原图不存在:' . $imageRelPath];
+        }
+
+        // 默认放大配置
+        $defaultParams = [
+            'resize_mode' => 0,
+            'show_extras_results' => true,
+            'gfpgan_visibility' => 0,
+            'codeformer_visibility' => 0,
+            'codeformer_weight' => 0,
+            'upscaling_resize' => 2.45,
+            'upscaling_crop' => true,
+            'upscaler_1' => 'R-ESRGAN 4x+ Anime6B',
+            'upscaler_2' => 'None',
+            'extras_upscaler_2_visibility' => 0,
+            'upscale_first' => false
+        ];
+
+        // 合并配置参数
+        $params = array_merge($defaultParams, $options);
+
+        // 编码原始图片
+        try {
+            $imgData = file_get_contents($imgPath);
+            if ($imgData === false) {
+                throw new Exception('无法读取图片文件');
+            }
+            $params['image'] = base64_encode($imgData);
+        } catch (Exception $e) {
+            return ['code' => 1, 'msg' => '图片读取失败:' . $e->getMessage()];
+        }
+
+        $apiUrl = "http://20.0.17.233:45001/sdapi/v1/extra-single-image";
+        $headers = ['Content-Type: application/json'];
+
+        // 调用接口
+        $ch = curl_init();
+        curl_setopt_array($ch, [
+            CURLOPT_URL => $apiUrl,
+            CURLOPT_RETURNTRANSFER => true,
+            CURLOPT_POST => true,
+            CURLOPT_HTTPHEADER => $headers,
+            CURLOPT_POSTFIELDS => json_encode($params),
+            CURLOPT_TIMEOUT => 120
+        ]);
+
+        $response = curl_exec($ch);
+        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+        $curlErr = curl_error($ch);
+        curl_close($ch);
+
+        // 网络请求失败
+        if ($curlErr) {
+            return ['code' => 1, 'msg' => '请求失败:' . $curlErr];
+        }
+
+        // 状态码错误
+        if ($httpCode !== 200) {
+            return ['code' => 1, 'msg' => 'API请求失败,HTTP状态码:' . $httpCode];
+        }
+
+        // 解析响应
+        $data = json_decode($response, true);
+        if (json_last_error() !== JSON_ERROR_NONE) {
+            return ['code' => 1, 'msg' => 'API返回数据解析失败:' . json_last_error_msg()];
+        }
+
+        if (empty($data['image'])) {
+            return ['code' => 1, 'msg' => '接口未返回有效的图像数据'];
+        }
+
+        // 保存新图片
+        try {
+            $baseName = pathinfo($imageRelPath, PATHINFO_FILENAME);
+            $ext = pathinfo($imageRelPath, PATHINFO_EXTENSION);
+            $outputDir = 'uploads/extra_image/';
+            $outputPath = ROOT_PATH . 'public/' . $outputDir;
+
+            if (!is_dir($outputPath)) {
+                mkdir($outputPath, 0755, true);
+            }
+
+            $saveFileName = $baseName . '-hd.' . $ext;
+            $saveFullPath = $outputPath . $saveFileName;
+            $resultImg = base64_decode($data['image']);
+
+            if ($resultImg === false || file_put_contents($saveFullPath, $resultImg) === false) {
+                throw new Exception('保存图片失败');
+            }
+
+            return [
+                'code' => 0,
+                'msg' => '高清图生成成功',
+                'data' => [
+                    'url' => '/' . $outputDir . $saveFileName,
+                    'original_size' => filesize($imgPath),
+                    'processed_size' => filesize($saveFullPath),
+                    'resolution' => getimagesize($saveFullPath)
+                ]
+            ];
+        } catch (Exception $e) {
+            return ['code' => 1, 'msg' => '保存失败:' . $e->getMessage()];
+        }
+    }
+
     /**
      * 通用 API 调用方法(支持重试机制)
      *

+ 5 - 1
application/service/ImageService.php

@@ -68,7 +68,7 @@ class ImageService{
 
             $arr = array_map(function ($item) use ($task_id) {
                 $item['type'] = '图生文';
-                $item['chain_next'] = ['文生文', '文生图','图生图'];
+                $item['chain_next'] = ['文生文', '文生图','图生图','高清放大'];
                 $item['task_id'] = $task_id;
                 return $item;
             }, $arr);
@@ -98,6 +98,10 @@ class ImageService{
                     $insertData['model'] = "realisticVisionV51_v51VAE-inpainting.safetensors [f0d4872d24]";
                     $insertData['model_name'] = '图生图';
                     break;
+                case '高清放大':
+                    $insertData['model'] = "";
+                    $insertData['model_name'] = '高清放大';
+                    break;
                 default:
                     return false;
             }