Please bookmark this page to avoid losing your image tool!

Android Ringtone Music Player And Photo Aspect Ratio Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, title = "Telephone Ringtone Mp3", artist = "Android Sound Player", lyrics = "🎵 Ring... Ring... Ring... 🎵", accentColor = "#3ddc84") {
    // Create the main wrapper container representing the Android MP3 Player UI
    const container = document.createElement('div');
    container.style.position = 'relative';
    container.style.width = '100%';
    container.style.maxWidth = '800px';
    container.style.aspectRatio = '2.55 / 1';
    container.style.borderRadius = '16px';
    container.style.overflow = 'hidden';
    container.style.fontFamily = '"Roboto", "Segoe UI", sans-serif';
    container.style.backgroundColor = '#121212';
    container.style.boxShadow = '0 8px 24px rgba(0,0,0,0.5)';
    container.style.margin = '0 auto';

    // Set up canvas to crop image dynamically to exact 2.55:1 aspect ratio
    const canvas = document.createElement('canvas');
    canvas.style.position = 'absolute';
    canvas.style.top = '0';
    canvas.style.left = '0';
    canvas.style.width = '100%';
    canvas.style.height = '100%';
    canvas.style.objectFit = 'cover';

    const targetRatio = 2.55;
    // Set a high resolution for crisp rendering
    canvas.width = 1000;
    canvas.height = Math.round(1000 / targetRatio);

    const ctx = canvas.getContext('2d');
    const imgRatio = originalImg.width / originalImg.height;

    // Calculate center-crop dimensions for 2.55:1
    let sWidth, sHeight, sx, sy;
    if (imgRatio > targetRatio) {
        // Image is wider than 2.55:1
        sHeight = originalImg.height;
        sWidth = sHeight * targetRatio;
        sx = (originalImg.width - sWidth) / 2;
        sy = 0;
    } else {
        // Image is taller than 2.55:1
        sWidth = originalImg.width;
        sHeight = sWidth / targetRatio;
        sx = 0;
        sy = (originalImg.height - sHeight) / 2;
    }

    ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, 0, 0, canvas.width, canvas.height);
    container.appendChild(canvas);

    // Overlay to ensure text readability (gradients)
    const overlay = document.createElement('div');
    overlay.style.position = 'absolute';
    overlay.style.inset = '0';
    overlay.style.background = 'linear-gradient(to bottom, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0) 30%, rgba(0,0,0,0.85) 100%)';
    container.appendChild(overlay);

    // Song Lyrics Element
    const lyricEl = document.createElement('div');
    lyricEl.style.position = 'absolute';
    lyricEl.style.top = '15%';
    lyricEl.style.left = '50%';
    lyricEl.style.transform = 'translateX(-50%)';
    lyricEl.style.color = '#fff';
    lyricEl.style.fontSize = 'min(3vw, 16px)';
    lyricEl.style.fontStyle = 'italic';
    lyricEl.style.textShadow = '0px 2px 4px rgba(0,0,0,0.8)';
    lyricEl.style.opacity = '0.9';
    lyricEl.style.textAlign = 'center';
    lyricEl.style.whiteSpace = 'nowrap';
    lyricEl.innerText = lyrics;
    container.appendChild(lyricEl);

    // Bottom Player UI container (Android Style)
    const playerUI = document.createElement('div');
    playerUI.style.position = 'absolute';
    playerUI.style.bottom = '15%';
    playerUI.style.left = '50%';
    playerUI.style.transform = 'translateX(-50%)';
    playerUI.style.width = '90%';
    playerUI.style.display = 'flex';
    playerUI.style.flexDirection = 'column';
    playerUI.style.gap = '10px';
    container.appendChild(playerUI);

    // Track Info & Time Row
    const infoRow = document.createElement('div');
    infoRow.style.display = 'flex';
    infoRow.style.justifyContent = 'space-between';
    infoRow.style.alignItems = 'flex-end';

    const trackInfo = document.createElement('div');
    const titleEl = document.createElement('div');
    titleEl.textContent = title;
    titleEl.style.color = '#fff';
    titleEl.style.fontWeight = 'bold';
    titleEl.style.fontSize = 'min(4vw, 20px)';
    titleEl.style.textShadow = '0 1px 3px rgba(0,0,0,0.8)';
    titleEl.style.marginBottom = '2px';

    const artistEl = document.createElement('div');
    artistEl.textContent = artist;
    artistEl.style.color = '#e0e0e0';
    artistEl.style.fontSize = 'min(2.5vw, 13px)';

    trackInfo.appendChild(titleEl);
    trackInfo.appendChild(artistEl);
    infoRow.appendChild(trackInfo);

    const timeEl = document.createElement('div');
    timeEl.textContent = '0:00 / 0:30';
    timeEl.style.color = '#e0e0e0';
    timeEl.style.fontSize = 'min(2.5vw, 13px)';
    timeEl.style.fontFamily = 'monospace';
    infoRow.appendChild(timeEl);
    playerUI.appendChild(infoRow);

    // Controls & Progress Bar Row
    const controlRow = document.createElement('div');
    controlRow.style.display = 'flex';
    controlRow.style.alignItems = 'center';
    controlRow.style.gap = '16px';

    const playBtn = document.createElement('button');
    playBtn.innerHTML = '▶'; // Play icon
    playBtn.style.width = 'min(10vw, 44px)';
    playBtn.style.height = 'min(10vw, 44px)';
    playBtn.style.borderRadius = '50%';
    playBtn.style.border = 'none';
    playBtn.style.backgroundColor = accentColor; 
    playBtn.style.color = '#000';
    playBtn.style.fontSize = '18px';
    playBtn.style.cursor = 'pointer';
    playBtn.style.display = 'flex';
    playBtn.style.justifyContent = 'center';
    playBtn.style.alignItems = 'center';
    playBtn.style.paddingLeft = '4px'; // Offset visual center for play icon
    playBtn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.4)';
    playBtn.style.transition = 'transform 0.1s ease';

    playBtn.onmousedown = () => playBtn.style.transform = 'scale(0.95)';
    playBtn.onmouseup = () => playBtn.style.transform = 'scale(1)';
    playBtn.onmouseleave = () => playBtn.style.transform = 'scale(1)';

    const progressContainer = document.createElement('div');
    progressContainer.style.flexGrow = '1';
    progressContainer.style.height = '4px';
    progressContainer.style.backgroundColor = 'rgba(255,255,255,0.3)';
    progressContainer.style.borderRadius = '2px';
    progressContainer.style.position = 'relative';

    const progressBar = document.createElement('div');
    progressBar.style.width = '0%';
    progressBar.style.height = '100%';
    progressBar.style.backgroundColor = accentColor;
    progressBar.style.borderRadius = '2px';
    progressBar.style.transition = 'width 0.1s linear';
    
    // Playhead dot
    const playHead = document.createElement('div');
    playHead.style.position = 'absolute';
    playHead.style.right = '-6px';
    playHead.style.top = '-4px';
    playHead.style.width = '12px';
    playHead.style.height = '12px';
    playHead.style.backgroundColor = accentColor;
    playHead.style.borderRadius = '50%';
    playHead.style.boxShadow = '0 0 4px rgba(0,0,0,0.5)';
    progressBar.appendChild(playHead);

    progressContainer.appendChild(progressBar);
    controlRow.appendChild(playBtn);
    controlRow.appendChild(progressContainer);
    playerUI.appendChild(controlRow);

    // --- Audio Rendering Logic via Web Audio API (Synthesizing a Phone Ringtone) ---
    let audioCtx, osc1, osc2, gainNode;
    let playing = false;
    let ringInterval, timeInterval, lyricAnimation;
    let currentSeconds = 0;
    const totalDuration = 30; // Max allowed mp3 playback duration

    function formatTime(s) {
        const min = Math.floor(s / 60);
        const sec = Math.floor(s % 60);
        return `${min}:${sec < 10 ? '0' : ''}${sec}`;
    }

    playBtn.addEventListener('click', () => {
        // Initialize Audio context securely on user gesture
        if (!audioCtx) {
            const AudioContext = window.AudioContext || window.webkitAudioContext;
            audioCtx = new AudioContext();

            // Synthesize standard UK/European telephone ring frequency (400Hz + 450Hz sine waves)
            osc1 = audioCtx.createOscillator();
            osc1.type = 'sine';
            osc1.frequency.value = 400;

            osc2 = audioCtx.createOscillator();
            osc2.type = 'sine';
            osc2.frequency.value = 450;

            gainNode = audioCtx.createGain();
            gainNode.gain.value = 0; 
            
            const compressor = audioCtx.createDynamicsCompressor();

            osc1.connect(gainNode);
            osc2.connect(gainNode);
            gainNode.connect(compressor);
            compressor.connect(audioCtx.destination);

            osc1.start();
            osc2.start();
        }

        if (audioCtx.state === 'suspended') {
            audioCtx.resume();
        }

        if (playing) {
            // PAUSE
            playing = false;
            playBtn.innerHTML = '▶';
            playBtn.style.paddingLeft = '4px';
            clearInterval(ringInterval);
            clearInterval(timeInterval);
            clearInterval(lyricAnimation);
            lyricEl.style.opacity = '0.9';
            gainNode.gain.setTargetAtTime(0, audioCtx.currentTime, 0.05);
        } else {
            // PLAY
            playing = true;
            playBtn.innerHTML = '⏸';
            playBtn.style.paddingLeft = '0px';

            // Ringtone generation (Cadence: double ring, then silence)
            let step = 0;
            const volumeMax = 0.4;
            ringInterval = setInterval(() => {
                step = (step + 1) % 30; // 3 sec loop (30 steps of 100ms)
                // On: 0-4, Off: 4-6, On: 6-10, Off: 10-30
                if (step < 4 || (step >= 6 && step < 10)) {
                    gainNode.gain.setTargetAtTime(volumeMax, audioCtx.currentTime, 0.05);
                } else {
                    gainNode.gain.setTargetAtTime(0, audioCtx.currentTime, 0.05);
                }
            }, 100);

            // Progress bar and time handling
            timeInterval = setInterval(() => {
                currentSeconds += 0.1;
                if (currentSeconds >= totalDuration) {
                    currentSeconds = 0; 
                }
                progressBar.style.width = (currentSeconds / totalDuration * 100) + '%';
                timeEl.textContent = `${formatTime(currentSeconds)} / ${formatTime(totalDuration)}`;
            }, 100);

            // Pulse lyrics text visually while playing
            lyricAnimation = setInterval(() => {
                const fade = (Math.sin(Date.now() / 250) * 0.3) + 0.7;
                lyricEl.style.opacity = fade.toString();
            }, 50);
        }
    });

    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

This tool allows users to transform images into stylized visual representations of an Android-style music player. It automatically crops and adjusts photos to a specific 2.55:1 aspect ratio and overlays a simulated media player interface, complete with song titles, artist names, lyrics, and playback controls. Beyond visual editing, it includes a synthesized audio feature that generates a telephone ringtone effect when the play button is pressed. This tool is ideal for creators looking to make unique social media assets, music-themed concept art, or stylized UI mockups.

Leave a Reply

Your email address will not be published. Required fields are marked *