Просмотр исходного кода

gpt-image-2图片模型更换中转站

lh 2 дней назад
Родитель
Сommit
634ec3cde2
1 измененных файлов с 108 добавлено и 2 удалено
  1. 108 2
      app/Services/AIGeneration/AIImageGenerationService.php

+ 108 - 2
app/Services/AIGeneration/AIImageGenerationService.php

@@ -465,8 +465,8 @@ class AIImageGenerationService
                     
                     $pic_name = 'ai_generation_gpt_' . time() . '_' . uniqid() . '.png';
                     
-                    // 压缩PNG图片
-                    $compressedData = compressRemoteImageUrlToSize($imageStream);
+                    // 压缩PNG图片
+                    $compressedData = $this->compressImageStream($imageStream);
                     $url = uploadStreamByTos('image', $compressedData, $pic_name);
                     
                     $result_urls[] = $url;
@@ -1621,4 +1621,110 @@ class AIImageGenerationService
 
         return 'auto';
     }
+
+    /**
+     * 压缩图片流(针对PNG格式)
+     *
+     * @param string $imageStream 图片二进制数据
+     * @param int $maxBytes 最大字节数(默认3MB)
+     * @return string|null 压缩后的图片二进制数据,失败时返回原数据
+     */
+    private function compressImageStream(string $imageStream, int $maxBytes = 3 * 1024 * 1024): ?string
+    {
+        try {
+            // 检查图片类型
+            $imgInfo = @getimagesizefromstring($imageStream);
+            if (!$imgInfo) {
+                dLog('generate')->warning('无法识别图片类型,返回原始数据');
+                return $imageStream;
+            }
+
+            $mime = $imgInfo['mime'] ?? '';
+            
+            // 只处理PNG,JPEG不做有损压缩
+            if ($mime === 'image/jpeg') {
+                return $imageStream;
+            }
+
+            // 如果已经小于最大限制,直接返回
+            if (strlen($imageStream) <= $maxBytes) {
+                return $imageStream;
+            }
+
+            // 载入图像对象
+            $srcImg = @imagecreatefromstring($imageStream);
+            if (!$srcImg) {
+                dLog('generate')->warning('无法创建图像资源,返回原始数据');
+                return $imageStream;
+            }
+
+            $origW = imagesx($srcImg);
+            $origH = imagesy($srcImg);
+
+            // 逐步降低质量直到满足大小要求
+            $quality = 9; // PNG压缩等级 0-9
+            $scaleFactor = 1.0;
+            $maxAttempts = 10;
+            $attempt = 0;
+            $compressedData = null;
+
+            while ($attempt < $maxAttempts) {
+                $attempt++;
+
+                // 如果需要缩放
+                if ($scaleFactor < 1.0) {
+                    $newW = (int)($origW * $scaleFactor);
+                    $newH = (int)($origH * $scaleFactor);
+                    $resizedImg = imagecreatetruecolor($newW, $newH);
+                    
+                    // 保持透明度
+                    imagealphablending($resizedImg, false);
+                    imagesavealpha($resizedImg, true);
+                    
+                    imagecopyresampled($resizedImg, $srcImg, 0, 0, 0, 0, $newW, $newH, $origW, $origH);
+                    $targetImg = $resizedImg;
+                } else {
+                    $targetImg = $srcImg;
+                }
+
+                // 输出到内存
+                ob_start();
+                imagepng($targetImg, null, $quality);
+                $compressedData = ob_get_clean();
+
+                if ($scaleFactor < 1.0) {
+                    imagedestroy($targetImg);
+                }
+
+                // 检查大小
+                $size = strlen($compressedData);
+                dLog('generate')->info('图片压缩尝试', [
+                    'attempt' => $attempt,
+                    'quality' => $quality,
+                    'scale' => $scaleFactor,
+                    'size' => $size,
+                    'target' => $maxBytes
+                ]);
+
+                if ($size <= $maxBytes) {
+                    break;
+                }
+
+                // 调整参数
+                if ($quality > 0) {
+                    $quality--;
+                } else {
+                    $scaleFactor *= 0.9; // 每次缩小10%
+                }
+            }
+
+            imagedestroy($srcImg);
+            
+            return $compressedData ?: $imageStream;
+
+        } catch (\Exception $e) {
+            dLog('generate')->error('图片压缩失败', ['error' => $e->getMessage()]);
+            return $imageStream;
+        }
+    }
 }