sikeaditya's picture
Update templates/index.html
1359dc2 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OCR Translation - English to Hindi</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.loader {
border: 3px solid #f3f3f3;
border-radius: 50%;
border-top: 3px solid #3498db;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
display: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.drop-zone {
border: 2px dashed #cbd5e0;
transition: all 0.3s ease;
}
.drop-zone:hover {
border-color: #3498db;
background-color: #f8fafc;
}
.result-box {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.result-box:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
}
.custom-file-input::-webkit-file-upload-button {
visibility: hidden;
width: 0;
}
.custom-file-input::before {
content: 'Choose File';
display: inline-block;
background: #3498db;
color: white;
padding: 8px 16px;
border-radius: 5px;
cursor: pointer;
}
.translate-btn {
background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
transition: all 0.3s ease;
}
.translate-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
}
.error-message {
background-color: #fee2e2;
border: 1px solid #ef4444;
color: #b91c1c;
padding: 10px;
border-radius: 5px;
margin-bottom: 15px;
display: none;
}
</style>
</head>
<body class="min-h-screen py-12 px-4">
<div class="container mx-auto max-w-4xl">
<!-- Header -->
<div class="text-center mb-12">
<h1 class="text-4xl font-bold text-gray-800 mb-3">
<i class="fas fa-language mr-2"></i>OCR Translation
</h1>
<p class="text-gray-600">English to Hindi Translation with Image Recognition</p>
</div>
<!-- Error Message Box -->
<div id="errorMessage" class="error-message mb-4">
<i class="fas fa-exclamation-circle mr-2"></i>
<span id="errorText">Error message will appear here</span>
</div>
<!-- Main Content -->
<div class="bg-white rounded-xl shadow-lg p-8 mb-8">
<!-- Upload Section -->
<div class="drop-zone rounded-lg p-8 text-center mb-6">
<div class="mb-4">
<i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
<h3 class="text-lg font-semibold text-gray-700 mb-2">Upload Image</h3>
<p class="text-sm text-gray-500 mb-4">Support for PNG, JPG, JPEG, GIF, BMP</p>
</div>
<input type="file"
id="imageInput"
accept="image/*"
class="custom-file-input w-full mb-4 cursor-pointer">
<button id="translateBtn" onclick="processImage()"
class="translate-btn w-full py-3 px-6 text-white rounded-lg font-medium flex items-center justify-center">
<i class="fas fa-sync-alt mr-2"></i>
<span>Translate Now</span>
</button>
<div id="loader" class="loader mx-auto mt-4"></div>
</div>
<!-- Preview Section -->
<div id="previewSection" class="hidden mb-6">
<h3 class="text-lg font-semibold text-gray-700 mb-3">Image Preview</h3>
<img id="imagePreview" class="max-w-full h-auto rounded-lg shadow" src="" alt="Preview">
</div>
<!-- Results Section -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Original Text -->
<div class="result-box rounded-xl p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">
<i class="fas fa-file-alt mr-2"></i>Extracted Text
</h3>
<button onclick="copyText('extractedText')" class="text-blue-500 hover:text-blue-600">
<i class="far fa-copy"></i>
</button>
</div>
<div id="extractedText" class="p-4 bg-gray-50 rounded-lg min-h-[150px] text-gray-700">
<!-- Extracted text will appear here -->
</div>
</div>
<!-- Translated Text -->
<div class="result-box rounded-xl p-6">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-700">
<i class="fas fa-language mr-2"></i>Hindi Translation
</h3>
<button onclick="copyText('translatedText')" class="text-blue-500 hover:text-blue-600">
<i class="far fa-copy"></i>
</button>
</div>
<div id="translatedText" class="p-4 bg-gray-50 rounded-lg min-h-[150px] text-gray-700"
style="font-family: 'Noto Sans Devanagari', sans-serif;">
<!-- Translated text will appear here -->
</div>
</div>
</div>
</div>
</div>
<script>
function showError(message) {
const errorDiv = document.getElementById('errorMessage');
const errorText = document.getElementById('errorText');
errorText.textContent = message;
errorDiv.style.display = 'block';
}
function hideError() {
document.getElementById('errorMessage').style.display = 'none';
}
// Image preview functionality
document.getElementById('imageInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('imagePreview').src = e.target.result;
document.getElementById('previewSection').classList.remove('hidden');
}
reader.readAsDataURL(file);
hideError(); // Hide any previous errors
}
});
// Copy text functionality
function copyText(elementId) {
const text = document.getElementById(elementId).textContent;
navigator.clipboard.writeText(text).then(() => {
// Show a brief notification
const element = document.getElementById(elementId);
const originalBackground = element.style.backgroundColor;
element.style.backgroundColor = '#e8f5e9';
setTimeout(() => {
element.style.backgroundColor = originalBackground;
}, 500);
});
}
function processImage() {
const fileInput = document.getElementById('imageInput');
const loader = document.getElementById('loader');
const extractedTextDiv = document.getElementById('extractedText');
const translatedTextDiv = document.getElementById('translatedText');
if (!fileInput.files[0]) {
showError('Please select an image first');
return;
}
const formData = new FormData();
formData.append('file', fileInput.files[0]);
// Hide previous errors
hideError();
// Show loader and clear previous results
loader.style.display = 'block';
extractedTextDiv.textContent = '';
translatedTextDiv.textContent = '';
fetch('/upload', {
method: 'POST',
body: formData
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.error || `Server error: ${response.status}`);
});
}
return response.json();
})
.then(data => {
extractedTextDiv.textContent = data.original_text;
translatedTextDiv.textContent = data.translated_text;
// Check if the response contains error messages
if (data.original_text && data.original_text.startsWith('Could not extract text')) {
showError(data.original_text);
}
})
.catch(error => {
console.error('Error:', error);
showError(error.message || 'An unknown error occurred');
extractedTextDiv.textContent = 'Error: Could not process image.';
translatedTextDiv.textContent = 'Translation unavailable due to processing error.';
})
.finally(() => {
loader.style.display = 'none';
});
}
</script>
</body>
</html>