多🌹444收拾收拾计算机视觉手机手机手机手机4大尺寸惆怅长岑长
??????????????????????????С??????????????P??????????????????????????????????????????????????????^??????????
????j??????????
? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!PK QGW]ÌóˆMâ â P database/migrations/2025_01_20_080747_is_advanced_image_to_user_openai_table.phpnu „[µü¤ boolean('is_advanced_image')->default(false)->after('request_id');
});
}
public function down(): void {}
};
PK QGW]„°ô½Ö Ö C database/migrations/2025_01_20_080747_advanced_image_migrations.phpnu „[µü¤ exists();
if ($openai) {
return;
}
OpenAIGenerator::query()->create($data);
}
} catch (\Exception $exception) {
}
}
public function down(): void {}
};
PK QGW]žJ�’Þ Þ database/resources/db.jsonnu „[µü¤ {
"user_id": null,
"title": "AI Image Generator",
"description": "Create stunning images in seconds.",
"slug": "ai_image_generator",
"active": 1,
"questions": "[{\"name\":\"description\",\"type\":\"textarea\",\"question\":\"Describe the Image\",\"select\":\"\"},{\"name\":\"size\",\"type\":\"select\",\"question\":\"Image Resolution\",\"select\":\"\"}]",
"image": "",
"premium": 0,
"type": "image",
"created_at": "2023-03-20 14:22:02",
"updated_at": "2024-09-20 14:23:53",
"prompt": null,
"custom_template": 0,
"tone_of_voice": 0,
"color": "#D1C5DE",
"filters": "development",
"package": null
}
PK QGW]¸ËÓ� � extension.jsonnu „[µü¤ {
"name": "Advanced Image",
"type": "extension",
"version": "1.5.0",
"description": "Advanced Image extension for magicai"
}
PK QGW]À„× System/.DS_Storenu „[µü¤ Bud1 bwspblob ¸ H t t pbwspblob ¸bplist00Ö]ShowStatusBar[ShowToolbar[ShowTabView_ContainerShowSidebar\WindowBounds[ShowSidebar _{{368, 408}, {920, 436}} #/;R_klmnoŠ
‹ H t t pvSrnlong @ € @ € @ € @ E DSDB ` € @ € @ € @ PK QGW]z§BÇê# ê# % System/Services/NanoBananaService.phpnu „[µü¤ tool) {
'reimagine' => $this->reimagine(),
'remove_background' => $this->remove_background(),
'inpainting' => $this->inpainting(),
'remove_text' => $this->remove_text(),
'sketch_to_image' => $this->sketch_to_image(),
'replace_background' => $this->replace_background(),
'cleanup' => $this->cleanup(),
'style_transfer' => $this->style_transfer(),
'image_relight' => $this->image_relight(),
default => [
'status' => 'error',
'message' => 'Unable to process action.',
]
};
}
/**
images: [
'https://betamagicai.liquid-themes.com/uploads/ordek.jpg',
]
*/
public function sketch_to_image(): array
{
try {
$response = self::generateImage(
prompt: 'Turn this sketch into a photorealistic image. Prompt: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('sketch_file'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function remove_background(): array
{
try {
$response = self::generateImage(
prompt: 'Remove the background, keeping only the main subject.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function cleanup(): array
{
$this->request->validate([
'description' => 'required',
]);
try {
$response = self::generateImage(
prompt: $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function remove_text(): array
{
try {
$response = self::generateImage(
prompt: 'Remove all visible text while preserving the image content.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function inpainting(): array
{
try {
$response = self::generateImage(
prompt: $this->request->get('description') . ' Blend naturally with the rest of the image.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function replace_background(): array
{
try {
$response = self::generateImage(
prompt: 'Replace the background with: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function reimagine(): array
{
try {
$response = self::generateImage(
prompt: 'Reimagine this image as: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function style_transfer(): array
{
$this->request->validate([
'uploaded_image' => 'required|image',
'reference_image' => 'required|image',
]);
try {
$response = self::generateImage(
prompt: 'Apply the general visual style of: [image 1] to [image 2].' . $this->request->get('description'),
entity: EntityEnum::FLUX_PRO_KONTEXT_MAX_MULTI,
images: self::createImageUrls([
$this->request->file('uploaded_image'),
$this->request->file('reference_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function image_relight(): array
{
$this->request->validate([
'uploaded_image' => 'required|image',
'image_relight' => 'required|image',
]);
try {
$response = self::generateImage(
prompt: 'Adjust image lighting to: [image 1] to [image 2]. Prompt: ' . $this->request->get('description') . ' style: ' . $this->request->get('style'),
entity: EntityEnum::FLUX_PRO_KONTEXT_MAX_MULTI,
images: self::createImageUrls([
$this->request->file('uploaded_image'),
$this->request->file('image_relight'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function responseArray($response): array
{
return [
'task_id' => $response->json('request_id'),
'photo' => '',
'status' => 'success',
'task_status' => 'IN_PROGRESS',
'message' => 'Task is processing.',
'link' => $response->json('response_url'),
];
}
public function checkStatus(UserOpenai $task): UserOpenai
{
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Key ' . ApiHelper::setFalAIKey(),
])->get($task['payload']['link']);
if ($response->ok() && $images = $response->json('images')) {
$image = Arr::first($images);
$path = $this->downloadAndSaveImageFromUrl($image['url']);
$task->update([
'title' => $this->title($path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
return $task;
}
public function setTool(string $tool): self
{
$this->tool = $tool;
return $this;
}
public function setRequest(Request $request): NanoBananaService
{
$this->request = $request;
return $this;
}
}
PK QGW]2õˆ$ $ System/Services/FalAIService.phpnu „[µü¤ tool) {
'reimagine' => $this->reimagine(),
'remove_background' => $this->remove_background(),
'inpainting' => $this->inpainting(),
'remove_text' => $this->remove_text(),
'sketch_to_image' => $this->sketch_to_image(),
'replace_background' => $this->replace_background(),
'cleanup' => $this->cleanup(),
'style_transfer' => $this->style_transfer(),
'image_relight' => $this->image_relight(),
default => [
'status' => 'error',
'message' => 'Unable to process action.',
]
};
}
/**
images: [
'https://betamagicai.liquid-themes.com/uploads/ordek.jpg',
]
*/
public function sketch_to_image(): array
{
try {
$response = self::generateImage(
prompt: 'Turn this sketch into a photorealistic image. Prompt: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('sketch_file'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function remove_background(): array
{
try {
$response = self::generateImage(
prompt: 'Remove the background, keeping only the main subject. Transparent.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function cleanup(): array
{
try {
$response = self::generateImage(
prompt: 'Clean up the masked area to remove imperfections or unwanted elements. Preserve the other areas.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
$this->request->file('mask_file'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function remove_text(): array
{
try {
$response = self::generateImage(
prompt: 'Remove all visible text while preserving the image content.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function inpainting(): array
{
try {
$response = self::generateImage(
prompt: $this->request->get('description') . ' Blend naturally with the rest of the image.',
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function replace_background(): array
{
try {
$response = self::generateImage(
prompt: 'Replace the background with: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function reimagine(): array
{
try {
$response = self::generateImage(
prompt: 'Reimagine this image as: ' . $this->request->get('description'),
images: self::createImageUrls([
$this->request->file('uploaded_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function style_transfer(): array
{
$this->request->validate([
'uploaded_image' => 'required|image',
'reference_image' => 'required|image',
]);
try {
$response = self::generateImage(
prompt: 'Apply the general visual style of: [image 1] to [image 2].' . $this->request->get('description'),
entity: EntityEnum::FLUX_PRO_KONTEXT_MAX_MULTI,
images: self::createImageUrls([
$this->request->file('uploaded_image'),
$this->request->file('reference_image'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function image_relight(): array
{
$this->request->validate([
'uploaded_image' => 'required|image',
'image_relight' => 'required|image',
]);
try {
$response = self::generateImage(
prompt: 'Adjust image lighting to: [image 1] to [image 2]. Prompt: ' . $this->request->get('description') . ' style: ' . $this->request->get('style'),
entity: EntityEnum::FLUX_PRO_KONTEXT_MAX_MULTI,
images: self::createImageUrls([
$this->request->file('uploaded_image'),
$this->request->file('image_relight'),
])
);
return $this->responseArray($response);
} catch (Exception $exception) {
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
}
public function responseArray($response): array
{
return [
'task_id' => $response->json('request_id'),
'photo' => '',
'status' => 'success',
'task_status' => 'IN_PROGRESS',
'message' => 'Task is processing.',
'link' => $response->json('response_url'),
];
}
public function checkStatus(UserOpenai $task): UserOpenai
{
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Key ' . ApiHelper::setFalAIKey(),
])->get($task['payload']['link']);
if ($response->ok() && $images = $response->json('images')) {
$image = Arr::first($images);
$path = $this->downloadAndSaveImageFromUrl($image['url']);
$task->update([
'title' => $this->title($path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
return $task;
}
public function setTool(string $tool): self
{
$this->tool = $tool;
return $this;
}
public function setRequest(Request $request): FalAIService
{
$this->request = $request;
return $this;
}
}
PK QGW]?éqÁ Á # System/Services/Traits/UseImage.phpnu „[µü¤ $prompt];
if (empty($images)) {
return $request;
}
// $imageUrls = self::createImageUrls($images);
// FLUX_PRO_KONTEXT with single image uses different parameter
if ($entity === EntityEnum::FLUX_PRO_KONTEXT && count($images) === 1) {
$request['image_url'] = Arr::first($images);
} else {
$request['image_urls'] = $images;
}
return $request;
}
private static function makeApiRequest(EntityEnum $entity, array $request): Response
{
$url = self::$baseApiUrl . $entity->value . '/max';
return Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Key ' . ApiHelper::setFalAIKey(),
])->post($url, $request);
}
private static function handleResponse(Response $response): Response
{
if ($response->successful() && $requestId = $response->json('request_id')) {
return $response;
}
$errorMessage = $response->json('detail') ?: 'Check your FAL API key.';
throw new RuntimeException(__($errorMessage));
}
public static function createImageUrls(array $images): array
{
if (empty($images)) {
return [];
}
$baseUrl = url(self::$uploadPath);
return array_map(
fn ($image) => $baseUrl . '/' . $image->store('falai', 'public'),
$images
);
}
}
PK QGW]6b^,™ ™ ( System/Services/Traits/HasNanoBanana.phpnu „[µü¤ $prompt];
if (empty($images)) {
return $request;
}
$request['image_urls'] = $images;
// $request['image_urls'] = [
// 'https://storage.googleapis.com/falserverless/example_inputs/nano-banana-edit-input.png',
// 'https://cdn.mos.cms.futurecdn.net/ntFmJUZ8tw3ULD3tkBaAtf-650-80.jpg.webp',
// ];
$request['num_images'] = 1;
$request['output_format'] = 'png';
return $request;
}
private static function makeApiRequest(EntityEnum $entity, array $request): Response
{
$url = self::$baseApiUrl . $entity->value;
return Http::withHeaders([
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Authorization' => 'Key ' . ApiHelper::setFalAIKey(),
])->post($url, $request);
}
private static function handleResponse(Response $response): Response
{
if ($response->successful() && $requestId = $response->json('request_id')) {
return $response;
}
$errorMessage = $response->json('detail') ?: 'Check your FAL API key.';
throw new RuntimeException(__($errorMessage));
}
public static function createImageUrls(array $images): array
{
if (empty($images)) {
return [];
}
$baseUrl = url(self::$uploadPath);
return array_map(
fn ($image) => $baseUrl . '/' . $image->store('falai', 'public'),
$images
);
}
}
PK QGW]ÝŠÂ Â + System/Services/Traits/HasDownloadImage.phpnu „[µü¤ successful()) {
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
$fileName = Str::uuid() . '.' . $extension;
$path = 'image-editor/' . $fileName;
Storage::disk('uploads')->put($path, $response->body());
return $this->imagePath($path);
}
return null;
}
}
PK QGW]q›È-‚, ‚, * System/Services/AdvancedFreepikService.phpnu „[µü¤ 'ai/beta/text-to-image/reimagine-flux',
'style_transfer' => 'https://api.freepik.com/v1/ai/image-style-transfer',
// 'remove_background' => 'https://api.freepik.com/v1/ai/beta/remove-background',
'upscale' => 'ai/image-upscaler',
'image-relight' => 'ai/image-relight',
];
public function webhook(UserOpenai $task, array $data): void
{
if (data_get($data, 'status') === 'COMPLETED') {
$image = Arr::first(data_get($data, 'generated'));
$path = $this->downloadAndSaveImageFromUrl($image);
$task->update([
'title' => str_replace('image-editor/', '', $path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
}
public function checkStatus(UserOpenai $task): UserOpenai
{
$payload = $task->payload;
$response = $this->requestGet($payload['link']);
if (! is_array($response) && $response->json('data.status') === 'COMPLETED') {
$image = Arr::first($response->json('data.generated'));
$path = $this->downloadAndSaveImageFromUrl($image);
$task->update([
'title' => str_replace('image-editor/', '', $path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
return $task;
}
public function generate(string $model, array $params): array
{
$response = match ($model) {
'reimagine' => $this->reimagine($params),
'image_relight' => $this->imageRelight($params),
// 'remove_background' => $this->removeBackground($params),
'upscale' => $this->upscale($params),
'style_transfer' => $this->styleTransfer($params),
default => [
'status' => 'error',
'message' => 'Invalid model.',
],
};
return $response;
}
private function styleTransfer($params): PromiseInterface|array|Response
{
$image = $this->encodeFile($params['uploaded_image']);
$reference_image = $this->encodeFile($params['reference_image']);
$data = [
'image' => $image,
'reference_image' => $reference_image,
'webhook_url' => config('app.url') . '/api/webhook/advanced-image/freepik',
'prompt' => $params['description'] ?? 'enhance clarity sharp details',
'style_strength' => 85,
'structure_strength' => 60,
'engine' => 'colorful_anime',
];
$response = $this->requestPost(self::ENDPOINTS['style_transfer'], $data);
if (is_array($response)) {
return $response;
}
if ($response->json('task_id') && $response->json('task_status')) {
return [
'task_status' => $response->json('task_status'),
'task_id' => $response->json('task_id'),
'status' => 'success',
'photo' => null,
'message' => 'Task is processing.',
'link' => 'ai/image-style-transfer/' . $response->json('task_id'),
];
}
return [
'task_status' => 'error',
'task_id' => null,
'status' => 'error',
'message' => 'Unable to process action.',
];
}
private function imageRelight(array $params)
{
request()->validate([
'image_relight' => 'required',
'description' => 'required',
]);
$image = $this->encodeFile($params['uploaded_image']);
$transfer_light_from_reference_image = $this->encodeFile($params['image_relight']);
$data = [
'image' => $image,
'prompt' => $params['description'],
'transfer_light_from_reference_image' => $transfer_light_from_reference_image,
'light_transfer_strength' => 100,
'interpolate_from_original' => false,
'change_background' => true,
'style' => $params['style'],
'webhook_url' => config('app.url') . '/api/webhook/advanced-image/freepik',
];
$response = $this->requestPost(self::ENDPOINTS['upscale'], $data);
if (is_array($response)) {
return $response;
}
if ($response->json('data.task_id') && $response->json('data.status')) {
return [
'task_status' => $response->json('data.status'),
'task_id' => $response->json('data.task_id'),
'status' => 'success',
'photo' => null,
'message' => 'Task is processing.',
'link' => 'ai/image-relight/' . $response->json('data.task_id'),
];
}
return [
'task_status' => 'error',
'task_id' => null,
'status' => 'error',
'message' => 'Unable to process action.',
];
}
private function upscale($params): PromiseInterface|array|Response
{
$image = $this->encodeFile($params['uploaded_image']);
$data = [
'image' => $image,
'webhook_url' => config('app.url') . '/api/webhook/advanced-image/freepik',
'scale_factor' => '2x',
'optimized_for'=> 'standard',
'prompt' => $params['description'] ?? 'enhance clarity sharp details',
'creativity' => 2,
'hdr' => 1,
'resemblance' => 0,
'fractality' => -1,
'engine' => 'magnific_sparkle',
];
$response = $this->requestPost(self::ENDPOINTS['upscale'], $data);
if (is_array($response)) {
return $response;
}
if ($response->json('data.task_id') && $response->json('data.status')) {
return [
'task_status' => $response->json('data.status'),
'task_id' => $response->json('data.task_id'),
'status' => 'success',
'photo' => null,
'message' => 'Task is processing.',
'link' => 'ai/image-upscaler/' . $response->json('data.task_id'),
];
}
return [
'task_status' => 'error',
'task_id' => null,
'status' => 'error',
'message' => 'Unable to process action.',
];
}
private function removeBackground($params) {}
public function reimagine($params): string|array
{
request()->validate(['description' => 'required|string']);
$image = $this->encodeFile($params['uploaded_image']);
$data = [
'image' => $image,
'prompt' => $params['description'],
'imagination' => $params['imagination'] ?? 'wild',
'aspect_ratio' => $params['aspect_ratio'] ?? 'square_1_1',
];
$response = $this->requestPost(self::ENDPOINTS['reimagine'], $data);
if (is_array($response)) {
return $response;
}
if ($response->json('task_id') && $response->json('status') === 'COMPLETED') {
$image = Arr::first($response->json('generated'));
$path = $this->downloadAndSaveImageFromUrl($image);
if ($path) {
return [
'task_status' => $response->json('status'),
'status' => 'success',
'task_id' => $response->json('task_id'),
'photo' => $path,
'link' => 'ai/image-upscaler/' . $response->json('data.task_id'),
];
}
}
return [
'task_status' => 'error',
'task_id' => null,
'status' => 'error',
'message' => 'Unable to process action.',
];
}
public function downloadAndSaveImageFromUrl($url): ?string
{
// Resmin içeriğini çek
$response = Http::get($url);
if ($response->successful()) {
// Dosya uzantısını tahmin et
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
// Benzersiz bir dosya adı oluştur
$fileName = Str::uuid() . '.' . $extension;
// Storage path (örnek: storage/app/public/images)
$path = 'image-editor/' . $fileName;
// Dosyayı kaydet
Storage::disk('public')->put($path, $response->body());
// İsteğe bağlı: URL'yi döndür (örnek: http://.../storage/images/abc.jpg)
return $this->imagePath($path);
}
return null;
}
private function encodeFile($file): string
{
if (empty($file)) {
throw new RuntimeException('Make selection on image first');
}
return base64_encode(file_get_contents($file->getRealPath()));
}
public function requestGet($url, $contentType = 'application/json'): PromiseInterface|array|Response
{
$http = Http::withHeaders([
'Content-Type' => $contentType,
'Accept' => 'application/json',
'x-freepik-api-key' => $this->getApiKey(),
])
->baseUrl('https://api.freepik.com/v1/')
->get('ai/image-relight');
if ($http->successful()) {
return $http;
}
$error = $http->json('message');
return [
'status' => 'error',
'message' => $error ?? 'Unable to process action.',
];
}
public function requestPost($url, $data, $contentType = 'application/json'): PromiseInterface|array|Response
{
$http = Http::withHeaders([
'Content-Type' => $contentType,
'Accept' => 'application/json',
'x-freepik-api-key' => $this->getApiKey(),
])
->baseUrl('https://api.freepik.com/v1/')
->post($url, $data);
if ($http->successful()) {
return $http;
}
$error = $http->json('message');
return [
'status' => 'error',
'message' => $error ?? 'Unable to process action.',
];
}
private function getApiKey(): ?string
{
return setting('freepik_api_key');
}
}
PK QGW]“³´· · ! System/Services/OpenAIService.phpnu „[µü¤ tool) {
'reimagine' => $this->reimagineHandle(),
'cleanup' => $this->cleanupHandle(),
'remove_background' => $this->removeBackgroundHandle(),
'sketch_to_image' => $this->sketchToImageHandle(),
'inpainting' => $this->inpaintingHandle(),
'style_transfer' => $this->styleTransferHandle(),
'reference_image' => $this->referenceImageHandle(),
'remove_text' => $this->removeTextHandle(),
default => [],
};
}
private function removeTextHandle(): array
{
$this->request->validate([
'uploaded_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('uploaded_image')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image])
->setPrompt('Remove all visible text from the selected area of the image and fill the region with natural background content, matching the surrounding textures and colors.')
->generate();
}
// Remove all visible text from the selected area of the image and fill the region with natural background content, matching the surrounding textures and colors.
private function styleTransferHandle(): array
{
$this->request->validate([
'uploaded_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
'reference_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('uploaded_image')->store('', ['disk' => 'uploads']);
$style = 'uploads/' . $this->request->file('reference_image')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image, $style])
->setPrompt('Apply style transfer to the image.')
->generate();
}
private function inpaintingHandle(): array
{
$this->request->validate([
'uploaded_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('uploaded_image')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image])
->setPrompt('Inpainting : ' . $this->request->input('description'))
->generate();
}
private function sketchToImageHandle(): array
{
$this->request->validate([
'sketch_file' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('sketch_file')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image])
->setPrompt('sketch to image : ' . $this->request->input('description'))
->generate();
}
private function removeBackgroundHandle(): array
{
$this->request->validate([
'uploaded_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('uploaded_image')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image])
->setPrompt('Remove the background of the image and make it transparent.')
->generate();
}
private function cleanupHandle(): array
{
$this->request->validate([
'uploaded_image' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
'mask_file' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$image = 'uploads/' . $this->request->file('uploaded_image')->store('', ['disk' => 'uploads']);
$mask = 'uploads/' . $this->request->file('mask_file')->store('', ['disk' => 'uploads']);
return app(CreateImageEditService::class)
->setImages([$image])
->setMask($mask)
->setPrompt('Remove the areas marked in the mask from the image. Keep the rest of the image intact.')
->generate();
}
private function reimagineHandle(): array
{
$this->request->validate([
'images' => 'required|array',
'images.*' => 'required|image|mimes:jpeg,png,jpg,gif|max:4096',
]);
$images = $this->request->file('images');
$imagePaths = [];
foreach ($images as $image) {
$imagePaths[] = 'uploads/' . $image->store('', ['disk' => 'uploads']);
}
if (count($imagePaths) === 0) {
return [
'status' => false,
'message' => 'No images uploaded.',
];
}
$service = app(CreateImageEditService::class)
->setImages($imagePaths)
->setPrompt($this->request->input('description'))
->generate();
return $service;
}
public function setTool(string $tool): self
{
$this->tool = $tool;
return $this;
}
public function setRequest(Request $request): self
{
$this->request = $request;
return $this;
}
}
PK QGW]G¿Èj2 2 ) System/Services/AdvancedNovitaService.phpnu „[µü¤ 'https://api.novita.ai/v3/remove-background',
'merge_face' => 'https://api.novita.ai/v3/merge-face',
'replace_background' => 'https://api.novita.ai/v3/replace-background',
'upscale' => 'https://api.novita.ai/v3/async/upscale',
'reimagine' => 'https://api.novita.ai/v3/reimagine',
'remove_text' => 'https://api.novita.ai/v3/remove-text',
'cleanup' => 'https://api.novita.ai/v3/cleanup',
'text_to_image' => 'https://api.novita.ai/v3/async/txt2img',
'inpainting' => 'https://api.novita.ai/v3/async/inpainting',
'check_status' => 'https://api.novita.ai/v3/async/task-result?task_id=',
];
public function __construct()
{
$this->client = new Client;
}
public function webhook(UserOpenai $task, array $data): void
{
$image = data_get($data, '0.image_url');
if ($image) {
$path = $this->downloadAndSaveImageFromUrl($image);
$task->update([
'title' => $this->title($path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
}
public function generate(string $model, array $params): array
{
$action = $this->handleAction($model, $params);
if (isset($action['task']['task_id'])) {
if ($model === 'merge_face') {
$action['image_type'] = 'png';
}
return $this->processTaskWithImage($action);
}
if (isset($action['task_id'])) {
return [
'task_id' => $action['task_id'],
'photo' => '',
'status' => 'success',
'task_status' => 'IN_PROGRESS',
'message' => 'Task is processing.',
'link' => 'https://api.novita.ai/v3/async/task-result?task_id=' . $action['task_id'],
];
}
return [
'status' => 'error',
'message' => $action['message'] ?? 'Unable to process action.',
];
}
private function handleAction(string $model, array $params): array
{
return match ($model) {
'reimagine' => $this->reimagine($params),
'remove_background' => $this->removeBackground($params),
'replace_background' => $this->replaceBackground($params),
'text_to_image' => $this->textToImage($params),
'upscale' => $this->upscale($params),
'remove_text' => $this->removeText($params),
'cleanup' => $this->cleanup($params),
'inpainting' => $this->inpainting($params),
'merge_face' => $this->merge_face($params),
default => []
};
}
private function processTaskWithImage(array $action): array
{
if (isset($action['image_file'])) {
$imageType = $action['image_type'] ?? 'jpg';
$contents = base64_decode($action['image_file']);
$fileName = 'image-editor/' . Str::random(10) . '.' . $imageType;
Storage::disk('public')->put($fileName, $contents);
return [
'task_id' => $action['task']['task_id'],
'photo' => $this->imagePath($fileName),
'status' => 'completed',
];
}
return [
'task_id' => $action['task']['task_id'],
'photo' => null,
'status' => 'completed',
];
}
private function apiRequest(string $endpoint, array $payload): array
{
try {
$response = $this->client->post($endpoint, [
'headers' => [
'Authorization' => 'Bearer ' . setting('novita_api_key'),
'Content-Type' => 'application/json',
],
'json' => $payload,
]);
return json_decode($response->getBody()->getContents(), true);
} catch (Exception $exception) {
if (! $exception->hasResponse()) {
return ['type' => 'error', 'message' => __('Unknown error: No response from the server.')];
}
$responseBody = $exception->getResponse()->getBody();
$errorResponse = json_decode($responseBody, true);
if (! is_array($errorResponse)) {
return ['type' => 'error', 'message' => __('Unknown error: Invalid response format.')];
}
$message = $errorResponse['message'] ?? __('Unknown error');
$metadataMessage = '';
if (isset($errorResponse['metadata']) && is_array($errorResponse['metadata'])) {
$metadataMessage = $errorResponse['metadata']['image_file'] ?? '';
}
return ['type' => 'error', 'message' => trim($message . '. ' . $metadataMessage)];
}
}
private function inpainting(array $params): array
{
request()->validate([
'description' => 'required|string|max:1024',
], [
'description.required' => 'Please provide a prompt',
]);
$image = $this->encodeFile($params['photo']);
$mask = $this->encodeFile($params['mask']);
return $this->apiRequest(self::ENDPOINTS['inpainting'], [
'extra' => [
'response_image_type' => 'jpeg',
'webhook' => [
'url' => config('app.url') . '/api/webhook/advanced-image/novita',
],
'enable_nsfw_detection' => false,
],
'request' => [
'model_name' => 'realisticVisionV40_v40VAE-inpainting_81543.safetensors',
'prompt' => $params['description'],
'negative_prompt' => '(deformed iris, deformed pupils, semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime), text, cropped, out of frame, worst quality, low quality, jpeg artifacts, ugly, duplicate, morbid, mutilated, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, blurry, dehydrated, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, long neck, BadDream, UnrealisticDream',
'image_num' => 1,
'steps' => 25,
'seed' => -1,
'clip_skip' => 1,
'guidance_scale' => 7.5,
'sampler_name' => 'Euler a',
'mask_blur' => 1,
'inpainting_full_res' => 1,
'inpainting_full_res_padding'=> 32,
'inpainting_mask_invert' => 0,
'initial_noise_multiplier' => 1,
'strength' => 0.85,
'image_base64' => $image,
'mask_image_base64' => $mask,
],
]);
}
private function merge_face(array $params): array
{
$image = $this->encodeFile($params['photo']);
$faceImage = $this->encodeFile(request()->file('face_image'));
return $this->apiRequest(self::ENDPOINTS['merge_face'], [
'image_file' => $image,
'face_image_file' => $faceImage,
'extra' => [
'response_image_type' => 'png',
],
]);
}
private function reimagine(array $params): array
{
$image = $this->encodeFile($params['photo']);
return $this->apiRequest(self::ENDPOINTS['reimagine'], [
'image_file' => $image,
'extra' => ['response_image_type' => 'png'],
]);
}
private function removeBackground(array $params): array
{
$image = $this->encodeFile($params['photo']);
return $this->apiRequest(self::ENDPOINTS['remove_background'], [
'image_file' => $image,
'extra' => ['response_image_type' => 'png'],
]);
}
private function replaceBackground(array $params): array
{
$image = $this->encodeFile($params['photo']);
return $this->apiRequest(self::ENDPOINTS['replace_background'], [
'image_file' => $image,
'prompt' => $params['description'],
'extra' => ['response_image_type' => 'png'],
]);
}
private function textToImage(array $params): array
{
return $this->apiRequest(self::ENDPOINTS['text_to_image'], [
'request' => [
'model_name' => 'sd_xl_base_1.0.safetensors',
'prompt' => $params['description'],
'width' => 1024,
'height' => 1024,
'image_num' => 1,
'steps' => 20,
'seed' => 123,
'clip_skip' => 1,
'guidance_scale' => 7.5,
],
'extra' => ['response_image_type' => 'jpeg', 'enable_nsfw_detection' => false],
]);
}
private function upscale(array $params): array
{
$image = $this->encodeFile($params['photo']);
return $this->apiRequest(self::ENDPOINTS['upscale'], [
'request' => [
'model_name' => 'RealESRGAN_x4plus_anime_6B',
'image_base64' => $image,
'scale_factor' => 2,
],
'extra' => ['response_image_type' => 'jpeg'],
]);
}
private function removeText(array $params): array
{
$image = $this->encodeFile($params['photo']);
return $this->safeApiRequest(self::ENDPOINTS['remove_text'], [
'image_file' => $image,
'extra' => ['response_image_type' => 'png'],
]);
}
private function cleanup(array $params): array
{
$image = $this->encodeFile($params['photo']);
$mask = $this->encodeFile($params['mask']);
return $this->apiRequest(self::ENDPOINTS['cleanup'], [
'image_file' => $image,
'mask_file' => $mask,
'extra' => ['response_image_type' => 'png'],
]);
}
private function encodeFile($file): string
{
if (empty($file)) {
throw new RuntimeException('Make selection on image first');
}
return base64_encode(file_get_contents($file->getRealPath()));
}
private function safeApiRequest(string $endpoint, array $payload): array
{
try {
return $this->apiRequest($endpoint, $payload);
} catch (Exception $exception) {
if ($exception->hasResponse()) {
$responseBody = $exception->getResponse()->getBody()->getContents();
$decodedResponse = json_decode($responseBody, true);
$errorMessage = $decodedResponse['message'] ?? 'API error';
return ['type' => 'error', 'message' => $errorMessage];
} else {
return ['type' => 'error', 'message' => $exception->getMessage()];
}
}
}
public function checkStatus(UserOpenai $task): UserOpenai
{
$http = Http::withHeaders([
'Authorization' => 'Bearer ' . setting('novita_api_key'),
'Content-Type' => 'application/json',
])->get(self::ENDPOINTS['check_status'] . $task['request_id']);
if ($http->json('task.status') === 'TASK_STATUS_SUCCEED' && is_array($http->json('images'))) {
$image = Arr::first($http->json('images'));
$path = $this->downloadAndSaveImageFromUrl($image['image_url']);
$task->update([
'title' => $this->title($path),
'status' => 'COMPLETED',
'output' => $path,
]);
}
return $task;
}
}
PK QGW]ºðk¦� � # System/Services/ClipDropService.phpnu „[µü¤ getAction()) {
'reimagine' => $this->reimagine(),
'remove_background' => $this->remove_background(),
'replace_background' => $this->replace_background(),
'sketch_to_image' => $this->sketch_to_image(),
'text_to_image' => $this->text_to_image(),
'upscale' => $this->upscale(),
'remove_text' => $this->remove_text(),
'uncrop' => $this->uncrop(),
'cleanup' => $this->cleanup(),
'inpainting' => $this->inpainting(),
default => [],
};
if (! is_array($action)) {
$fileName = 'image-editor/' . Str::random('10') . '.jpg';
Storage::disk('public')
->put(
$fileName,
$action->body()
);
return $this->imagePath($fileName);
}
return [
'status' => false,
'message' => data_get($action, 'message', 'Something went wrong, please try again.'),
];
}
public function inpainting()
{
return $this->request(
$this->baseUrl . 'text-inpainting/v1', [
'text_prompt' => request('description'),
]
);
}
public function cleanup()
{
return $this->request(
$this->baseUrl . 'cleanup/v1',
);
}
public function uncrop()
{
return $this->request(
$this->baseUrl . 'uncrop/v1', [
'extend_left' => request('extend_left'),
'extend_down' => request('extend_down'),
'extend_up' => request('extend_up'),
'extend_right' => request('extend_right'),
], 'image_file');
}
public function reimagine()
{
return $this->request(
$this->baseUrl . 'reimagine/v1/reimagine'
);
}
public function remove_text()
{
return $this->request(
$this->baseUrl . 'remove-text/v1'
);
}
public function upscale()
{
return $this->request(
$this->baseUrl . 'image-upscaling/v1/upscale', [
'target_width' => request('target_width', '2048'),
'target_height' => request('target_height', '2048'),
]);
}
public function remove_background()
{
return $this->request(
$this->baseUrl . 'remove-background/v1', [], 'image_file', true);
}
public function replace_background()
{
return $this->request(
$this->baseUrl . 'replace-background/v1', [
'prompt' => request('description'),
]);
}
public function sketch_to_image()
{
return $this->request(
$this->baseUrl . 'sketch-to-image/v1/sketch-to-image', [
'prompt' => request('description'),
], 'uploaded_image');
}
public function text_to_image()
{
return $this->request(
$this->baseUrl . 'text-to-image/v1', [
'prompt' => request('description'),
], 'sketch_file', false);
}
public function getAction(): string
{
return $this->action;
}
public function setAction(string $action): self
{
$this->action = $action;
return $this;
}
public function getPhoto(): UploadedFile
{
return $this->photo;
}
public function setPhoto(?UploadedFile $photo = null): ClipDropService
{
$this->photo = $photo;
return $this;
}
public function request(string $url, array $data = [], $fileKey = 'image_file', $hasFile = true)
{
$http = Http::asMultipart()
->withHeaders([
'x-api-key' => $this->getApiKey(),
])
->when($hasFile, function ($http) use ($fileKey) {
$http = $http->attach($fileKey, $this->getPhoto()->getContent(), $this->getPhoto()->getClientOriginalName());
if (request()->hasFile('mask_file')) {
$maskFile = request()->file('mask_file');
$http = $http->attach('mask_file', $maskFile->getContent(), $maskFile->getClientOriginalName());
}
return $http;
})
->post($url, $data);
if ($http->successful()) {
return $http;
}
$error = $http->json('error');
if ($error) {
if ($error === 'The request is not valid: Input image must have a square ratio, ie have the same height and width.') {
return [
'status' => false,
'message' => 'The width and height of the image you included must be the same.',
];
}
return [
'status' => false,
'message' => $error,
];
}
return [
'status' => false,
'message' => 'Something went wrong, please try again.',
];
}
public function getApiKey(): string
{
return setting('clipdrop_api_key', '');
}
}
PK QGW]o> ;
' System/AdvancedImageServiceProvider.phpnu „[µü¤ registerTranslations()
->registerViews()
->registerRoutes()
->registerMigrations();
}
protected function registerTranslations(): static
{
$this->loadTranslationsFrom(__DIR__ . '/../resources/lang', 'advanced-image');
return $this;
}
public function registerViews(): static
{
$this->loadViewsFrom([__DIR__ . '/../resources/views'], 'advanced-image');
return $this;
}
public function registerMigrations(): static
{
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
return $this;
}
private function registerRoutes(): static
{
$router = $this->router()
->group([
'middleware' => ['web', 'auth'],
], function (Router $router) {
$router
->prefix('dashboard')
->name('dashboard.')
->group(function (Router $router) {
$router->prefix('user')
->name('user.')
->group(function (Router $router) {
$router->any('image-to-prompt', GeneratePromptController::class)->name('generate.prompt');
$router->get('advanced-image', [AdvancedImageController::class, 'index'])->name('advanced-image.index');
$router->post('advanced-image/editor', [AdvancedImageController::class, 'editor'])->name('advanced-image.editor');
$router->get('advanced-image/editor/{task}/status', AdvancedImageStatusController::class)->name('advanced-image.editor.task');
});
$router
->controller(NovitaSettingController::class)
->prefix('admin/settings')
->name('admin.settings.')
->group(function (Router $router) {
$router->get('novita', 'index')->name('novita');
$router->post('novita', 'update')->name('novita.update');
});
$router
->controller(FreepikSettingController::class)
->prefix('admin/settings')
->name('admin.settings.')
->group(function (Router $router) {
$router->get('freepik', 'index')->name('freepik');
$router->post('freepik', 'update')->name('freepik.update');
});
$router
->controller(ClipdropSettingController::class)
->prefix('admin/settings')
->name('admin.settings.')
->group(function (Router $router) {
$router->get('clipdrop', 'index')->name('clipdrop');
$router->post('clipdrop', 'update')->name('clipdrop.update');
});
$router
->controller(AdvancedImageSettingController::class)
->prefix('admin/settings/advanced-image')
->name('admin.settings.advanced-image.')
->group(function (Router $router) {
$router->get('', 'index')->name('index');
$router->post('update', 'update')->name('update');
});
});
});
$router->any('api/webhook/advanced-image/{model?}', AdvancedImageWebhookController::class)
->middleware('api')
->name('webhook.advanced-image');
return $this;
}
private function router(): Router|Route
{
return $this->app['router'];
}
}
PK QGW]Þ¨•sZ Z System/cache018388/.htaccessnu „[µü¤
{{ __($tool['description']) }}