0) { $percent=floor(($uploaded/$upload_size)*100); $percent*=7;$percent+=10; // It lags behind a lot, after experimentation, this gives a more reasonable estimate of completion time. if ($percent>=100) { set_processing_message($lang["openai_image_edit__completing"]); } else { set_processing_message($lang["openai_image_edit__sending"] . " (" . $percent . "%)"); } } } if ($_SERVER['REQUEST_METHOD'] === 'POST') { set_processing_message($lang["openai_image_edit__preparing_images"]); $maskData = getval('mask',''); // Base64 encoded mask from the frontend $mode = getval('mode',''); $prompt = getval('prompt',''); // Decode the mask data from base64 list($type, $maskData) = explode(';', $maskData); list(, $maskData) = explode(',', $maskData); $maskData = base64_decode($maskData); if ($mode=="white" || $mode=="black") { $mask=imagecreatefromstring($maskData); // Get the width and height of the image $width = imagesx($mask); $height = imagesy($mask); // Create a new true color image with the same dimensions $newBackground = imagecreatetruecolor($width, $height); // Fill the new image with colour $shade=255; if ($mode=="black") {$shade=0;} $fill = imagecolorallocate($newBackground, $shade, $shade, $shade); imagefill($newBackground, 0, 0, $fill); // Copy the original image onto the white background // This will replace transparent areas with white imagecopy($newBackground, $mask, 0, 0, 0, 0, $width, $height); // Start output buffering to capture the image data in memory ob_start(); imagepng($newBackground); $imagedata = ob_get_clean(); // Free up memory imagedestroy($mask); imagedestroy($newBackground); // Return the image data as JSON with base64 encoding header('Content-Type: application/json'); echo json_encode(["image_base64" => base64_encode($imagedata)]); exit(); } if ($mode=="clone") { $mask=imagecreatefromstring($maskData); // Get the width and height of the image $width = imagesx($mask); $height = imagesy($mask); // Create a new true color image with the same dimensions $image = imagecreatefromstring($maskData); imagealphablending($image, true); imagesavealpha($image, true); // Clone parts of the surrounding image by moving it in an ever decreasing box for ($offset=300;$offset>0;$offset-=30) { imagecopy($image, $mask, -$offset, 0, 0, 0, $width, $height); imagecopy($image, $mask, 0, -$offset, 0, 0, $width, $height); imagecopy($image, $mask, $offset, 0, 0, 0, $width, $height); imagecopy($image, $mask, 0, $offset, 0, 0, $width, $height); } imagecopy($image, $mask, 0, 0, 0, 0, $width, $height); // Start output buffering to capture the image data in memory ob_start(); imagepng($image); $imagedata = ob_get_clean(); // Free up memory imagedestroy($mask); imagedestroy($image); // Return the image data as JSON with base64 encoding header('Content-Type: application/json'); echo json_encode(["image_base64" => base64_encode($imagedata)]); exit(); } // Prepare the OpenAI API request using multipart/form-data if ($mode=="edit") { $url = 'https://api.openai.com/v1/images/edits'; $model = "dall-e-2"; $content_type="multipart/form-data"; } if ($mode=="variation") { $url = 'https://api.openai.com/v1/images/variations'; $model = "dall-e-2"; $content_type="multipart/form-data"; } if ($mode=="generate") { $url = 'https://api.openai.com/v1/images/generations'; $model = "dall-e-3"; $content_type="application/json"; } $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'curlprogress'); curl_setopt($ch, CURLOPT_NOPROGRESS, false); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer $openai_gpt_api_key", "Content-Type: " . $content_type ]); // Improve the mask by replacing non transparent areas with black. This significantly reduces the time to send the mask to OpenAI as the compression is much better. $mask=imagecreatefromstring($maskData); // Set blending mode off to preserve transparency imagealphablending($mask, false); imagesavealpha($mask, true); // Get image dimensions $width = imagesx($mask); $height = imagesy($mask); // Loop through each pixel for ($x = 0; $x < $width; $x++) { for ($y = 0; $y < $height; $y++) { // Get the color and alpha of the current pixel $rgba = imagecolorat($mask, $x, $y); $alpha = ($rgba & 0x7F000000) >> 24; // Set the pixel to black with the same alpha $black = imagecolorallocatealpha($mask, 0, 0, 0, $alpha); imagesetpixel($mask, $x, $y, $black); } } // Re-render the mask ob_start(); imagepng($mask); $maskDataSimplified = ob_get_contents(); ob_end_clean(); // Prepare the data array using CURLFile for both image and mask $data = [ 'model' => $model, // Specify model (if applicable) 'n' => 1, 'size' => '1024x1024' ]; if ($mode=="edit" || $mode=="variation") { $data['image'] = new CURLStringFile($maskData, 'image/png'); } if ($mode=="edit" || $mode=="generate") { $data['prompt'] = $prompt; } if ($mode=="edit") { $data['mask'] = new CURLStringFile($maskDataSimplified, 'image/png'); } if ($mode=="generate") { $data=json_encode($data); } // Attach the form data curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // Execute the request and get the response $response = curl_exec($ch); // Check for errors in the cURL request if (curl_errno($ch)) { echo 'Error:' . curl_error($ch); } else { $json=json_decode($response,true); $url=$json["data"][0]["url"] ?? ""; if ($url!="") { header('Content-Type: application/json'); echo json_encode(["image_base64"=>base64_encode(file_get_contents($url))]); } else { echo $response; } } curl_close($ch); exit(); } include "../../../include/header.php"; ?>
$lang["backtoview"], "href" => generateURL($baseurl_short . "pages/view.php", ["ref" => $ref]) ], [ "title" => $lang["openai_image_edit__edit_with_ai"], "help" => "plugins/openai_image_edit" ] ]); ?>