Think of a precision measuring tool for screens and images - that's our DPI calculator! It figures out pixel density for monitors, print resolution for photos, and gaming sensitivity (eDPI) all in one place. Gamers get perfect aim, designers get crisp prints!
โ
Image: ${results.imageWidth}ร${results.imageHeight} pixels
๐ Print: ${results.printWidth}ร${results.printHeight} ${results.units}
๐ Recommended: 300+ DPI for photos, 150+ DPI for posters
๐ Copy Result
`;
}
// ========== MONITOR PPI CALCULATOR ==========
function calculateMonitorPPI() {
const screenWidth = parseFloat(document.getElementById('screenWidth').value);
const screenHeight = parseFloat(document.getElementById('screenHeight').value);
const diagonal = parseFloat(document.getElementById('screenDiagonal').value);
if (!screenWidth || !screenHeight || !diagonal) {
showError('Please fill in all fields for monitor PPI calculation');
return;
}
const diagonalPixels = Math.sqrt(screenWidth * screenWidth + screenHeight * screenHeight);
const ppi = diagonalPixels / diagonal;
const aspectRatio = Math.round((screenWidth / screenHeight) * 100) / 100;
const totalPixels = screenWidth * screenHeight;
const megapixels = totalPixels / 1000000;
// Calculate dot pitch (distance between pixels)
const dotPitch = 25.4 / ppi; // in millimeters
// Quality assessment for displays
let quality = 'Standard';
let qualityClass = 'quality-fair';
if (ppi >= 400) {
quality = 'Retina+';
qualityClass = 'quality-excellent';
} else if (ppi >= 300) {
quality = 'Retina';
qualityClass = 'quality-excellent';
} else if (ppi >= 200) {
quality = 'High';
qualityClass = 'quality-good';
} else if (ppi >= 100) {
quality = 'Standard';
qualityClass = 'quality-fair';
} else {
quality = 'Low';
qualityClass = 'quality-poor';
}
displayMonitorResults({
ppi: ppi.toFixed(1),
quality,
qualityClass,
aspectRatio,
megapixels: megapixels.toFixed(1),
dotPitch: dotPitch.toFixed(3),
screenWidth,
screenHeight,
diagonal
});
showOTA();
trackEvent('dpi_calculated', { type: 'monitor' });
}
function displayMonitorResults(results) {
const container = document.getElementById('monitorResults');
container.innerHTML = `
${results.ppi} PPI
${results.quality}
Pixel Density
${results.ppi} PPI
Dot Pitch
${results.dotPitch} mm
Aspect Ratio
${results.aspectRatio}:1
Total Pixels
${results.megapixels} MP
๐ฑ Resolution: ${results.screenWidth}ร${results.screenHeight} pixels
๐ Size: ${results.diagonal}" diagonal
๐ Retina displays typically have 300+ PPI
๐ Copy Result
`;
}
// ========== GAMING eDPI CALCULATOR ==========
function calculateGamingEDPI() {
const mouseDPI = parseFloat(document.getElementById('mouseDPI').value);
const gameSens = parseFloat(document.getElementById('gameSens').value);
const sensType = document.getElementById('sensType').value;
if (!mouseDPI || !gameSens) {
showError('Please fill in all fields for eDPI calculation');
return;
}
let sensitivity = gameSens;
if (sensType === 'percentage') {
sensitivity = gameSens / 100;
}
const eDPI = mouseDPI * sensitivity;
// Calculate cm/360 (approximate)
const cm360 = 103.2 / eDPI; // Approximate formula for most games
// Professional ranges for different games
let gameCategory = 'High Sensitivity';
let categoryClass = 'quality-fair';
if (eDPI <= 400) {
gameCategory = 'Pro Low Sens';
categoryClass = 'quality-excellent';
} else if (eDPI <= 800) {
gameCategory = 'Pro Range';
categoryClass = 'quality-good';
} else if (eDPI <= 1200) {
gameCategory = 'Medium Sens';
categoryClass = 'quality-fair';
} else {
gameCategory = 'High Sens';
categoryClass = 'quality-poor';
}
displayGamingResults({
eDPI: eDPI.toFixed(0),
cm360: cm360.toFixed(1),
gameCategory,
categoryClass,
mouseDPI,
gameSens,
sensType
});
showOTA();
trackEvent('dpi_calculated', { type: 'gaming' });
}
function displayGamingResults(results) {
const container = document.getElementById('gamingResults');
const sensDisplay = results.sensType === 'percentage' ? `${results.gameSens}%` : results.gameSens;
container.innerHTML = `
${results.eDPI} eDPI
${results.gameCategory}
Mouse DPI
${results.mouseDPI}
Game Sensitivity
${sensDisplay}
cm/360ยฐ
${results.cm360} cm
Category
${results.gameCategory}
๐ฎ eDPI = ${results.mouseDPI} ร ${sensDisplay}
๐ Distance to turn 360ยฐ: ${results.cm360} cm
๐ Pro players typically use 200-800 eDPI
๐ Copy Result
`;
}
// ========== DPI CONVERTER ==========
function calculateDPIConversion() {
const convWidth = parseFloat(document.getElementById('convWidth').value);
const convHeight = parseFloat(document.getElementById('convHeight').value);
const targetDPI = parseFloat(document.getElementById('targetDPI').value);
if (!convWidth || !convHeight || !targetDPI) {
showError('Please fill in all fields for DPI conversion');
return;
}
const maxWidthInches = convWidth / targetDPI;
const maxHeightInches = convHeight / targetDPI;
const maxWidthCm = maxWidthInches * 2.54;
const maxHeightCm = maxHeightInches * 2.54;
const megapixels = (convWidth * convHeight) / 1000000;
// Calculate different quality levels
const sizes = {
excellent: { dpi: 300, width: convWidth / 300, height: convHeight / 300 },
good: { dpi: 200, width: convWidth / 200, height: convHeight / 200 },
fair: { dpi: 150, width: convWidth / 150, height: convHeight / 150 },
minimum: { dpi: 72, width: convWidth / 72, height: convHeight / 72 }
};
displayConverterResults({
targetDPI,
maxWidthInches: maxWidthInches.toFixed(2),
maxHeightInches: maxHeightInches.toFixed(2),
maxWidthCm: maxWidthCm.toFixed(1),
maxHeightCm: maxHeightCm.toFixed(1),
megapixels: megapixels.toFixed(1),
convWidth,
convHeight,
sizes
});
showOTA();
trackEvent('dpi_calculated', { type: 'converter' });
}
function displayConverterResults(results) {
const container = document.getElementById('converterResults');
container.innerHTML = `
${results.maxWidthInches}" ร ${results.maxHeightInches}"
Max Size (inches)
${results.maxWidthInches}" ร ${results.maxHeightInches}"
Max Size (cm)
${results.maxWidthCm} ร ${results.maxHeightCm} cm
Target DPI
${results.targetDPI}
Image Size
${results.megapixels} MP
๐ Print Size Options
๐ธ 300 DPI (Photo Quality): ${results.sizes.excellent.width.toFixed(1)}" ร ${results.sizes.excellent.height.toFixed(1)}"
๐ 200 DPI (Good Quality): ${results.sizes.good.width.toFixed(1)}" ร ${results.sizes.good.height.toFixed(1)}"
๐ 150 DPI (Fair Quality): ${results.sizes.fair.width.toFixed(1)}" ร ${results.sizes.fair.height.toFixed(1)}"
๐ 72 DPI (Web/Screen): ${results.sizes.minimum.width.toFixed(1)}" ร ${results.sizes.minimum.height.toFixed(1)}"
๐ Image: ${results.convWidth}ร${results.convHeight} pixels
๐ฏ At ${results.targetDPI} DPI target resolution
๐ Higher DPI = better quality but smaller prints
๐ Copy Result
`;
}
// ========== SAMPLE USAGE FUNCTIONS ==========
function useSample(sampleId) {
const samples = {
'4k-photo': {
tab: 'print',
data: { imageWidth: 3840, imageHeight: 2160, printWidth: 8, printHeight: 6, units: 'inches' }
},
'1080p-monitor': {
tab: 'monitor',
data: { screenWidth: 1920, screenHeight: 1080, diagonal: 27 }
},
'gaming-pro': {
tab: 'gaming',
data: { mouseDPI: 800, gameSens: 0.35, sensType: 'decimal' }
},
'web-graphics': {
tab: 'converter',
data: { convWidth: 1920, convHeight: 1080, targetDPI: 72 }
}
};
const sample = samples[sampleId];
if (!sample) return;
// Switch to appropriate tab
switchTab(sample.tab);
// Fill in the data
Object.keys(sample.data).forEach(key => {
const element = document.getElementById(key);
if (element) {
element.value = sample.data[key];
}
});
// Highlight the calculate button
setTimeout(() => {
const calculateButtons = document.querySelectorAll('.btn');
const activeTab = document.querySelector('.tab-content.active');
const activeButton = activeTab.querySelector('.btn');
if (activeButton) {
activeButton.style.animation = 'pulse 0.5s ease-in-out';
setTimeout(() => activeButton.style.animation = '', 500);
activeButton.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
}, 100);
}
// ========== UTILITY FUNCTIONS ==========
// Copy to clipboard
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showNotification('Copied to clipboard!', 'success');
}).catch(() => {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showNotification('Copied to clipboard!', 'success');
});
}
// Show error
function showError(message) {
showNotification(message, 'error');
}
// Show notification toast
function showNotification(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// Show OTA section (dynamic)
function showOTA() {
const otaContainer = document.getElementById('otaContainer');
if (otaContainer && (otaContainer.style.display === 'none' || !otaContainer.style.display)) {
otaContainer.style.display = 'block';
// Attention-grabbing pulse effect
setTimeout(() => {
const otaHeader = document.querySelector('.ota-header h3');
if (otaHeader) {
otaHeader.style.animation = 'pulse 1s ease-in-out';
}
}, 100);
}
}
// Analytics tracking
function trackEvent(eventName, data = {}) {
if (typeof gtag !== 'undefined') {
gtag('event', eventName, {
'event_category': TOOL_CONFIG.category,
'event_label': TOOL_CONFIG.name,
...data
});
}
}
// ========== AI ASSISTANT FUNCTIONS ==========
// AI ๋ชจ๋ฌ ์ด๊ธฐ
function openAIModal() {
const modal = document.getElementById('aiModal');
if(modal) modal.classList.add('show');
// ํ์ฌ ์ํ์ ๋ฐ๋ผ ์ ์ ํ ํ๋ฉด ํ์
if (aiModalState.apiKey && aiModalState.currentView === 'gemini') {
showGeminiChat();
} else {
showAISelector();
}
updateAPIKeyStatus();
}
// AI ๋ชจ๋ฌ ๋ซ๊ธฐ
function closeAIModal() {
const modal = document.getElementById('aiModal');
if(modal) modal.classList.remove('show');
// 300ms ํ ์ํ ๋ฆฌ์
(์ ๋๋ฉ์ด์
์๋ฃ ํ)
setTimeout(() => {
aiModalState.currentView = 'selector';
showAISelector();
}, 300);
}
// AI ์ ํ ํ๋ฉด ํ์
function showAISelector() {
document.getElementById('aiModalTitle').textContent = 'Choose Your AI Assistant';
document.getElementById('aiSelector').style.display = 'flex';
document.getElementById('geminiChat').style.display = 'none';
document.getElementById('apiKeySetup').style.display = 'none';
aiModalState.currentView = 'selector';
}
// Gemini ์ฑํ
ํ๋ฉด ํ์
function showGeminiChat() {
document.getElementById('aiModalTitle').innerHTML = 'โจ Gemini AI Assistant';
document.getElementById('aiSelector').style.display = 'none';
document.getElementById('geminiChat').style.display = 'flex';
document.getElementById('apiKeySetup').style.display = 'none';
aiModalState.currentView = 'gemini';
// ์ด๊ธฐ ๋ฉ์์ง๊ฐ ์์ผ๋ฉด ์ถ๊ฐ
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages.innerHTML.trim()) {
addMessage('assistant', `Hello! I can help you with DPI calculations:
โข Understanding print DPI vs monitor PPI
โข Gaming eDPI optimization
โข Image resolution planning
โข Print size calculations
What would you like to know about DPI?`);
}
}
// API ํค ์ค์ ํ๋ฉด ํ์
function showAPIKeySetup() {
document.getElementById('aiModalTitle').textContent = 'Setup Gemini API';
document.getElementById('aiSelector').style.display = 'none';
document.getElementById('geminiChat').style.display = 'none';
document.getElementById('apiKeySetup').style.display = 'block';
aiModalState.currentView = 'setup';
}
// AI ์ ํ ์ฒ๋ฆฌ
function selectAI(aiType) {
switch(aiType) {
case 'chatgpt':
const toolContext = `I need help with DPI calculations. This is a DPI Calculator tool for print resolution, gaming eDPI, monitor PPI on WIA Pin Code platform.`;
const chatUrl = `https://chat.openai.com/?q=${encodeURIComponent(toolContext)}`;
window.open(chatUrl, '_blank');
closeAIModal();
trackEvent('ai_selection', { ai_type: 'chatgpt' });
break;
case 'claude':
const claudeContext = `I need help with DPI calculations. This is a DPI Calculator tool for print resolution, gaming eDPI, monitor PPI on WIA Pin Code platform.`;
const claudeUrl = `https://claude.ai/chat?q=${encodeURIComponent(claudeContext)}`;
window.open(claudeUrl, '_blank');
closeAIModal();
trackEvent('ai_selection', { ai_type: 'claude' });
break;
case 'gemini':
if (!aiModalState.apiKey) {
showAPIKeySetup();
} else {
showGeminiChat();
}
trackEvent('ai_selection', { ai_type: 'gemini' });
break;
}
}
// API ํค ์ ์ฅ
function saveGeminiApiKey() {
const apiKey = document.getElementById('geminiApiKeyInput').value.trim();
if (apiKey) {
localStorage.setItem('geminiApiKey', apiKey);
aiModalState.apiKey = apiKey;
showGeminiChat();
updateAPIKeyStatus();
} else {
alert('Please enter a valid API key');
}
}
// API ํค ์ํ ์
๋ฐ์ดํธ
function updateAPIKeyStatus() {
const statusEl = document.getElementById('apiKeyStatus');
if (aiModalState.apiKey) {
statusEl.innerHTML = 'Change API Key ';
} else {
statusEl.textContent = 'No API key set';
}
}
// ์ฑํ
๋ฉ์์ง ์ถ๊ฐ
function addMessage(type, content) {
const chatMessages = document.getElementById('chatMessages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
if (type === 'user') {
messageDiv.innerHTML = `You: ${content}`;
} else {
messageDiv.innerHTML = `โจ Gemini: ${content.replace(/\n/g, ' ')}`;
}
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Gemini์ ๋ฉ์์ง ์ ์ก
async function sendToGemini() {
const input = document.getElementById('geminiInput');
const message = input.value.trim();
if (!message) return;
// ์ฌ์ฉ์ ๋ฉ์์ง ์ถ๊ฐ
addMessage('user', message);
input.value = '';
// ๋ก๋ฉ ํ์
const loadingMsg = document.createElement('div');
loadingMsg.className = 'message assistant';
loadingMsg.innerHTML = 'โจ Gemini: Thinking...';
loadingMsg.id = 'loading-message';
document.getElementById('chatMessages').appendChild(loadingMsg);
try {
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${aiModalState.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
contents: [{
parts: [{
text: `Context: User is using DPI Calculator tool on WIA Pin Code platform.
This tool calculates print DPI, monitor PPI, gaming eDPI, and DPI conversions.
Current tab: ${currentTab}
User question: ${message}`
}]
}],
generationConfig: {
temperature: 0.7,
maxOutputTokens: 1000
}
})
});
const data = await response.json();
// ๋ก๋ฉ ๋ฉ์์ง ์ ๊ฑฐ
document.getElementById('loading-message').remove();
if (data.candidates && data.candidates[0] && data.candidates[0].content) {
const reply = data.candidates[0].content.parts[0].text;
addMessage('assistant', reply);
} else {
addMessage('assistant', 'Sorry, I could not generate a response. Please try again.');
}
} catch (error) {
// ๋ก๋ฉ ๋ฉ์์ง ์ ๊ฑฐ
document.getElementById('loading-message')?.remove();
if (error.message.includes('API key')) {
addMessage('error', 'Invalid API key. Please check your API key and try again.');
showAPIKeySetup();
} else {
addMessage('error', 'Failed to connect to Gemini. Please check your internet connection and try again.');
}
}
}
// ========== EVENT LISTENERS ==========
document.addEventListener('DOMContentLoaded', function() {
// Enter key support for inputs
document.querySelectorAll('.input-field').forEach(input => {
input.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
// Find the calculate button in the current active tab
const activeTab = document.querySelector('.tab-content.active');
const calculateBtn = activeTab.querySelector('.btn');
if (calculateBtn) {
calculateBtn.click();
}
}
});
});
// AI ๋ฒํผ ์ด๋ฒคํธ
document.getElementById('aiBtn').addEventListener('click', openAIModal);
// ๋ชจ๋ฌ ์ธ๋ถ ํด๋ฆญ์ ๋ซ๊ธฐ
document.getElementById('aiModal').addEventListener('click', function(e) {
if (e.target === this) {
closeAIModal();
}
});
// ์ํฐ ํค ์ง์ ๋ฐ ESC ํค๋ก ๋ชจ๋ฌ ๋ซ๊ธฐ
document.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
const geminiInput = document.getElementById('geminiInput');
if (document.activeElement === geminiInput) {
sendToGemini();
}
}
// ESC ํค๋ก ๋ชจ๋ฌ ๋ซ๊ธฐ
if (e.key === 'Escape') {
closeAIModal();
}
});
// ์ด๊ธฐ API ํค ์ํ ์
๋ฐ์ดํธ
updateAPIKeyStatus();
updateCurrentYear();
updateToolCount();
});
// Track WIA Pin Code clicks for analytics
document.querySelectorAll('a[href*="wia"]').forEach(link => {
link.addEventListener('click', function() {
trackEvent('wia_link_click', { link: link.textContent });
});
});
// ========== DYNAMIC TOOL COUNT ==========
// Update tool count dynamically
async function updateToolCount() {
try {
const response = await fetch('/api/tool-count.php');
const data = await response.json();
// Update dynamic tools description
document.querySelectorAll('.dynamic-tools-count').forEach(el => {
el.textContent = `${data.count}+ free online tools in 211 languages. No signup, no fees, just tools that work.`;
});
// Update "All X+ Tools" links
document.querySelectorAll('.dynamic-count').forEach(el => {
const prefix = el.getAttribute('data-text') || '';
const suffix = el.getAttribute('data-suffix') || '';
const icon = el.textContent.split(' ')[0] || '';
el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`;
});
} catch (error) {
// Fallback: use current actual count from server
const fallbackCount = 333;
document.querySelectorAll('.dynamic-tools-count').forEach(el => {
el.textContent = `${fallbackCount}+ free online tools in 211 languages. No signup, no fees, just tools that work.`;
});
document.querySelectorAll('.dynamic-count').forEach(el => {
const prefix = el.getAttribute('data-text') || '';
const suffix = el.getAttribute('data-suffix') || '';
const icon = el.textContent.split(' ')[0] || '';
el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`;
});
console.log('Tool count API not available, using current count:', fallbackCount);
}
}
// Update current year dynamically
function updateCurrentYear() {
const currentYear = new Date().getFullYear();
document.querySelectorAll('.current-year').forEach(el => {
el.textContent = currentYear;
});
}
// ========== ANALYTICS ==========
// Google Analytics
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXX');
// Track page view
trackEvent('page_view', {
tool: TOOL_CONFIG.name,
category: TOOL_CONFIG.category
});