Eidos

Installation Notice

The installation may currently fail. We recommend copying the code below and creating the extension manually in Eidos.

Convert Image to Anime Style

By: Mayne

Install Latest (v0.0.1)

Transform the image into anime/manga style artwork

export const meta = {
    type: "fileAction",
    funcName: "convertImageToAnime",
    fileAction: {
        name: "Convert Image to Anime Style",
        description: "Transform the image into anime/manga style artwork",
        extensions: [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"]
    },
}


export async function convertImageToAnime({ filePath }: { filePath: string }, ctx: Record<string, any>) {
    try {
        // Check for API key
        if (!ctx.env?.OPENROUTER_API_KEY) {
            throw new Error("OPENROUTER_API_KEY not found in environment variables. Please set it in script settings.")
        }

        // Read image file
        const imageBuffer = await eidos.currentSpace.fs.readFile(filePath)

        // Convert image to base64
        const base64Image = btoa(String.fromCharCode(...new Uint8Array(imageBuffer)))

        // Get file extension to determine MIME type
        const ext = filePath.split('.').pop()?.toLowerCase()
        const mimeTypes = {
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png',
            'gif': 'image/gif',
            'bmp': 'image/bmp',
            'webp': 'image/webp'
        }
        const mimeType = mimeTypes[ext] || 'image/jpeg'

        // Call OpenRouter API to generate anime style image
        const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${ctx.env.OPENROUTER_API_KEY}`,
                'Content-Type': 'application/json',
                'HTTP-Referer': window.location.href,
                'X-Title': 'Eidos Anime Converter'
            },
            body: JSON.stringify({
                model: 'google/gemini-3-pro-image-preview',
                messages: [
                    {
                        role: 'user',
                        content: [
                            {
                                type: 'text',
                                text: 'Please transform this image into anime/manga style. Convert the image to look like Japanese anime artwork with characteristic anime aesthetics including vibrant colors, stylized features, and anime-style rendering while maintaining the original composition and main elements.'
                            },
                            {
                                type: 'image_url',
                                image_url: {
                                    url: `data:${mimeType};base64,${base64Image}`
                                }
                            }
                        ]
                    }
                ],
                modalities: ['image', 'text'],
            })
        })

        if (!response.ok) {
            throw new Error(`API request failed: ${response.status} ${response.statusText}`)
        }

        const result = await response.json()

        if (result.choices && result.choices[0] && result.choices[0].message) {
            const message = result.choices[0].message

            if (message.images && message.images.length > 0) {
                // Process generated image
                const generatedImage = message.images[0]
                const imageUrl = generatedImage.image_url.url

                // Extract base64 data
                const base64Data = imageUrl.split(',')[1]
                const imageData = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0))

                // Generate new filename
                const pathParts = filePath.split('/')
                const fileName = pathParts[pathParts.length - 1]
                const baseName = fileName.includes('.') ? fileName.split('.').slice(0, -1).join('.') : fileName
                const animeFileName = `${baseName}_anime.png`

                pathParts[pathParts.length - 1] = animeFileName
                const animeFilePath = pathParts.join('/')

                // Save generated image
                await eidos.currentSpace.fs.writeFile(animeFilePath, imageData)

                eidos.currentSpace.notify({
                    title: "Anime Conversion Complete",
                    description: `Anime style version generated: "${animeFileName}"`,
                })

                return {
                    success: true,
                    originalFile: filePath,
                    animeFile: animeFilePath,
                    message: `Successfully generated anime style version image: ${animeFileName}`
                }
            } else if (message.content) {
                // If no image returned, may have text description
                throw new Error(`API returned text instead of image: ${message.content}`)
            } else {
                throw new Error('No image generated from API')
            }
        } else {
            throw new Error('No result returned from API')
        }

    } catch (error) {
        eidos.currentSpace.notify({
            title: "Anime Conversion Failed",
            description: `Failed to generate anime version: ${error.message}`,
        })

        return {
            success: false,
            error: error.message,
            message: `Failed to generate anime version: ${error.message}`
        }
    }
}

Information

Author
Mayne
Type
script/fileAction
Latest Version
0.0.1
Last Updated
11/21/2025
Published
11/21/2025

Version History

  • v0.0.1 11/21/2025