fix: snap aspect ratios to standard values for Gemini compatibility

Gemini image models reject arbitrary aspect ratios like 150:79
(computed via GCD from 1200×632 pixels). Replace GCD-based calculation
with a snap-to-nearest approach using 7 standard ratios (1:1, 3:2,
2:3, 4:3, 3:4, 16:9, 9:16). Also set modalities to ["image", "text"]
as required by some providers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
peptiderepo
2026-04-18 11:00:35 +07:00
parent a4405a5d32
commit dd406c5ba6

View File

@@ -222,11 +222,24 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
* @param string $model Resolved model id.
* @return array<string, mixed>
*/
/**
* Supported aspect ratios for OpenRouter image models (Gemini, GPT-5).
* Arbitrary ratios like 150:79 are rejected — must snap to one of these.
*
* @var array<int, array{w: int, h: int, ratio: float}>
*/
private const STANDARD_ASPECTS = [
[ 'w' => 1, 'h' => 1, 'ratio' => 1.0 ],
[ 'w' => 3, 'h' => 2, 'ratio' => 1.5 ],
[ 'w' => 2, 'h' => 3, 'ratio' => 0.6667 ],
[ 'w' => 4, 'h' => 3, 'ratio' => 1.3333 ],
[ 'w' => 3, 'h' => 4, 'ratio' => 0.75 ],
[ 'w' => 16, 'h' => 9, 'ratio' => 1.7778 ],
[ 'w' => 9, 'h' => 16, 'ratio' => 0.5625 ],
];
private function build_request_body( string $prompt, int $width, int $height, string $model ): array {
$gcd = $this->support->gcd( $width, $height );
$ar_w = (int) ( $width / $gcd );
$ar_h = (int) ( $height / $gcd );
$aspect = $ar_w . ':' . $ar_h;
$aspect = $this->snap_aspect_ratio( $width, $height );
return [
'model' => $model,
@@ -245,6 +258,30 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
];
}
/**
* Snap pixel dimensions to the nearest supported aspect ratio string.
* 1200×632 → ratio 1.8987 → nearest is 16:9 (1.7778).
*
* @param int $width Width in pixels.
* @param int $height Height in pixels.
* @return string Aspect ratio string like "16:9".
*/
private function snap_aspect_ratio( int $width, int $height ): string {
$target = $height > 0 ? (float) $width / (float) $height : 1.0;
$best = self::STANDARD_ASPECTS[0];
$best_d = abs( $target - $best['ratio'] );
foreach ( self::STANDARD_ASPECTS as $candidate ) {
$d = abs( $target - $candidate['ratio'] );
if ( $d < $best_d ) {
$best = $candidate;
$best_d = $d;
}
}
return $best['w'] . ':' . $best['h'];
}
/**
* Enforce the interface's dimension contract.
*