Add PHP image generator and documentation
- Create image.php script for generating bubble images - Add example usage HTML page for testing - Update README with documentation - Support multiple bubble styles - Gracefully handle missing fonts 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
221
image.php
Normal file
221
image.php
Normal file
@ -0,0 +1,221 @@
|
||||
<?php
|
||||
/**
|
||||
* SillyBubble Image Generator
|
||||
*
|
||||
* This script generates chat bubble images from text.
|
||||
* It takes a 'q' parameter for the text content and an optional 'style' parameter.
|
||||
*
|
||||
* Usage:
|
||||
* image.php?q=Hello+World
|
||||
* image.php?q=Hello+World&style=modern
|
||||
*/
|
||||
|
||||
// Set content type to PNG image
|
||||
header('Content-Type: image/png');
|
||||
|
||||
// Get parameters
|
||||
$text = isset($_GET['q']) ? urldecode($_GET['q']) : 'No text provided';
|
||||
$style = isset($_GET['style']) ? $_GET['style'] : 'default';
|
||||
|
||||
// Define styles
|
||||
$styles = [
|
||||
'default' => [
|
||||
'bg_color' => [245, 245, 245],
|
||||
'text_color' => [50, 50, 50],
|
||||
'border_color' => [200, 200, 200],
|
||||
'padding' => 20,
|
||||
'rounded' => 15,
|
||||
'font_size' => 14,
|
||||
'max_width' => 600,
|
||||
'line_height' => 20,
|
||||
'font' => __DIR__ . '/fonts/arial.ttf', // Adjust path as needed
|
||||
],
|
||||
'modern' => [
|
||||
'bg_color' => [66, 133, 244],
|
||||
'text_color' => [255, 255, 255],
|
||||
'border_color' => [59, 120, 220],
|
||||
'padding' => 20,
|
||||
'rounded' => 20,
|
||||
'font_size' => 14,
|
||||
'max_width' => 600,
|
||||
'line_height' => 20,
|
||||
'font' => __DIR__ . '/fonts/arial.ttf', // Adjust path as needed
|
||||
],
|
||||
'retro' => [
|
||||
'bg_color' => [255, 204, 102],
|
||||
'text_color' => [51, 51, 51],
|
||||
'border_color' => [204, 153, 0],
|
||||
'padding' => 20,
|
||||
'rounded' => 5,
|
||||
'font_size' => 14,
|
||||
'max_width' => 600,
|
||||
'line_height' => 20,
|
||||
'font' => __DIR__ . '/fonts/arial.ttf', // Adjust path as needed
|
||||
],
|
||||
'minimal' => [
|
||||
'bg_color' => [255, 255, 255],
|
||||
'text_color' => [0, 0, 0],
|
||||
'border_color' => [220, 220, 220],
|
||||
'padding' => 15,
|
||||
'rounded' => 0,
|
||||
'font_size' => 14,
|
||||
'max_width' => 600,
|
||||
'line_height' => 20,
|
||||
'font' => __DIR__ . '/fonts/arial.ttf', // Adjust path as needed
|
||||
],
|
||||
];
|
||||
|
||||
// Use default style if specified style doesn't exist
|
||||
if (!isset($styles[$style])) {
|
||||
$style = 'default';
|
||||
}
|
||||
|
||||
// Get style settings
|
||||
$config = $styles[$style];
|
||||
|
||||
// Check for fonts directory and create if it doesn't exist
|
||||
$fontsDir = __DIR__ . '/fonts';
|
||||
if (!is_dir($fontsDir)) {
|
||||
mkdir($fontsDir, 0755, true);
|
||||
}
|
||||
|
||||
// Fallback to a built-in font if the specified font file doesn't exist
|
||||
if (!file_exists($config['font'])) {
|
||||
// Try to find any TTF font in the fonts directory
|
||||
$foundFont = false;
|
||||
if (is_dir($fontsDir)) {
|
||||
$fontFiles = glob($fontsDir . '/*.ttf');
|
||||
if (!empty($fontFiles)) {
|
||||
$config['font'] = $fontFiles[0];
|
||||
$foundFont = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If no TTF font found, use built-in font
|
||||
if (!$foundFont) {
|
||||
$config['use_builtin_font'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a temporary image to calculate text dimensions
|
||||
$tempImage = imagecreatetruecolor(100, 100);
|
||||
$textColor = imagecolorallocate($tempImage, $config['text_color'][0], $config['text_color'][1], $config['text_color'][2]);
|
||||
|
||||
// Word wrap the text
|
||||
$words = explode(' ', $text);
|
||||
$lines = [];
|
||||
$currentLine = '';
|
||||
$maxWidth = $config['max_width'] - (2 * $config['padding']);
|
||||
|
||||
foreach ($words as $word) {
|
||||
$testLine = $currentLine . ' ' . $word;
|
||||
$testLine = ltrim($testLine); // Remove leading space
|
||||
|
||||
// Calculate width using built-in or TTF font
|
||||
if (isset($config['use_builtin_font'])) {
|
||||
$textWidth = imagefontwidth(5) * strlen($testLine);
|
||||
} else {
|
||||
$bbox = imagettfbbox($config['font_size'], 0, $config['font'], $testLine);
|
||||
$textWidth = $bbox[2] - $bbox[0];
|
||||
}
|
||||
|
||||
if ($textWidth > $maxWidth && $currentLine !== '') {
|
||||
$lines[] = $currentLine;
|
||||
$currentLine = $word;
|
||||
} else {
|
||||
$currentLine = $testLine;
|
||||
}
|
||||
}
|
||||
if ($currentLine !== '') {
|
||||
$lines[] = $currentLine;
|
||||
}
|
||||
|
||||
// Calculate image dimensions
|
||||
$lineCount = count($lines);
|
||||
if (isset($config['use_builtin_font'])) {
|
||||
$lineHeight = imagefontheight(5);
|
||||
$textHeight = $lineHeight * $lineCount;
|
||||
|
||||
// Find the longest line to determine width
|
||||
$textWidth = 0;
|
||||
foreach ($lines as $line) {
|
||||
$lineWidth = imagefontwidth(5) * strlen($line);
|
||||
$textWidth = max($textWidth, $lineWidth);
|
||||
}
|
||||
} else {
|
||||
$lineHeight = $config['line_height'];
|
||||
$textHeight = $lineHeight * $lineCount;
|
||||
|
||||
// Find the longest line to determine width
|
||||
$textWidth = 0;
|
||||
foreach ($lines as $line) {
|
||||
$bbox = imagettfbbox($config['font_size'], 0, $config['font'], $line);
|
||||
$lineWidth = $bbox[2] - $bbox[0];
|
||||
$textWidth = max($textWidth, $lineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// Add padding to dimensions
|
||||
$imgWidth = min($config['max_width'], $textWidth + (2 * $config['padding']));
|
||||
$imgHeight = $textHeight + (2 * $config['padding']);
|
||||
|
||||
// Create the bubble image
|
||||
$image = imagecreatetruecolor($imgWidth, $imgHeight);
|
||||
|
||||
// Allocate colors
|
||||
$bgColor = imagecolorallocate($image, $config['bg_color'][0], $config['bg_color'][1], $config['bg_color'][2]);
|
||||
$borderColor = imagecolorallocate($image, $config['border_color'][0], $config['border_color'][1], $config['border_color'][2]);
|
||||
$textColor = imagecolorallocate($image, $config['text_color'][0], $config['text_color'][1], $config['text_color'][2]);
|
||||
|
||||
// Fill background
|
||||
imagefill($image, 0, 0, $bgColor);
|
||||
|
||||
// Draw rounded rectangle (if rounded corners are requested)
|
||||
if ($config['rounded'] > 0) {
|
||||
// Draw filled rectangle
|
||||
imagefilledrectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $bgColor);
|
||||
|
||||
// Draw rounded corners - basic simulation for rounded corners
|
||||
// This could be improved with proper arc drawing
|
||||
$r = $config['rounded'];
|
||||
|
||||
// Top left corner
|
||||
imagefilledarc($image, $r, $r, $r * 2, $r * 2, 180, 270, $bgColor, IMG_ARC_PIE);
|
||||
|
||||
// Top right corner
|
||||
imagefilledarc($image, $imgWidth - $r - 1, $r, $r * 2, $r * 2, 270, 360, $bgColor, IMG_ARC_PIE);
|
||||
|
||||
// Bottom left corner
|
||||
imagefilledarc($image, $r, $imgHeight - $r - 1, $r * 2, $r * 2, 90, 180, $bgColor, IMG_ARC_PIE);
|
||||
|
||||
// Bottom right corner
|
||||
imagefilledarc($image, $imgWidth - $r - 1, $imgHeight - $r - 1, $r * 2, $r * 2, 0, 90, $bgColor, IMG_ARC_PIE);
|
||||
|
||||
// Draw border
|
||||
imagerectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $borderColor);
|
||||
} else {
|
||||
// Draw simple rectangle
|
||||
imagefilledrectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $bgColor);
|
||||
imagerectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $borderColor);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
$y = $config['padding'];
|
||||
foreach ($lines as $line) {
|
||||
if (isset($config['use_builtin_font'])) {
|
||||
// Use built-in font (less nice but always available)
|
||||
imagestring($image, 5, $config['padding'], $y, $line, $textColor);
|
||||
$y += imagefontheight(5);
|
||||
} else {
|
||||
// Use TrueType font (nicer but requires font file)
|
||||
imagettftext($image, $config['font_size'], 0, $config['padding'], $y + $config['font_size'], $textColor, $config['font'], $line);
|
||||
$y += $lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Output the image
|
||||
imagepng($image);
|
||||
|
||||
// Clean up
|
||||
imagedestroy($image);
|
||||
imagedestroy($tempImage);
|
Reference in New Issue
Block a user