Add visu on first part
This commit is contained in:
parent
70694d9333
commit
cfd71a15d6
4 changed files with 122 additions and 1 deletions
56
app.py
56
app.py
|
|
@ -274,6 +274,62 @@ def results(filename):
|
||||||
logger.error(f"Error serving file {filename}: {str(e)}")
|
logger.error(f"Error serving file {filename}: {str(e)}")
|
||||||
return jsonify({'error': f"Error serving file: {filename}"}), 500
|
return jsonify({'error': f"Error serving file: {filename}"}), 500
|
||||||
|
|
||||||
|
@app.route('/pdf-preview/<pdf_file>/<int:page_num>')
|
||||||
|
def pdf_preview(pdf_file, page_num):
|
||||||
|
"""Generate and serve a preview image of a PDF page"""
|
||||||
|
try:
|
||||||
|
import pdf2image
|
||||||
|
from PIL import Image
|
||||||
|
import io
|
||||||
|
|
||||||
|
# Check if PDF exists
|
||||||
|
if not os.path.exists(pdf_file):
|
||||||
|
return jsonify({'error': f'PDF file not found: {pdf_file}'}), 404
|
||||||
|
|
||||||
|
# Convert PDF page to image
|
||||||
|
logger.info(f"Generating preview for {pdf_file} page {page_num}")
|
||||||
|
|
||||||
|
# Use moderate DPI for preview (lower than analyzer's 200)
|
||||||
|
preview_dpi = 150
|
||||||
|
|
||||||
|
try:
|
||||||
|
pdf_images = pdf2image.convert_from_path(
|
||||||
|
pdf_file,
|
||||||
|
dpi=preview_dpi,
|
||||||
|
first_page=page_num,
|
||||||
|
last_page=page_num
|
||||||
|
)
|
||||||
|
|
||||||
|
if not pdf_images:
|
||||||
|
return jsonify({'error': f'Could not extract page {page_num} from PDF'}), 400
|
||||||
|
|
||||||
|
# Get the first (and only) page
|
||||||
|
pil_image = pdf_images[0]
|
||||||
|
|
||||||
|
# Resize if too large (max width 1200px for web preview)
|
||||||
|
max_width = 1200
|
||||||
|
if pil_image.width > max_width:
|
||||||
|
ratio = max_width / pil_image.width
|
||||||
|
new_height = int(pil_image.height * ratio)
|
||||||
|
pil_image = pil_image.resize((max_width, new_height), Image.LANCZOS)
|
||||||
|
|
||||||
|
# Convert to bytes
|
||||||
|
img_io = io.BytesIO()
|
||||||
|
pil_image.save(img_io, 'PNG', optimize=True)
|
||||||
|
img_io.seek(0)
|
||||||
|
|
||||||
|
return send_file(img_io, mimetype='image/png',
|
||||||
|
as_attachment=False,
|
||||||
|
download_name=f'{pdf_file}_page_{page_num}_preview.png')
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error converting PDF to image: {str(e)}")
|
||||||
|
return jsonify({'error': f'Error converting PDF to image: {str(e)}'}), 500
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error generating PDF preview: {str(e)}")
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
@app.route('/check-environment')
|
@app.route('/check-environment')
|
||||||
def check_environment():
|
def check_environment():
|
||||||
"""Endpoint to check the environment and available scripts"""
|
"""Endpoint to check the environment and available scripts"""
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,12 @@
|
||||||
|
|
||||||
<div id="analyzer-status" class="status hidden"></div>
|
<div id="analyzer-status" class="status hidden"></div>
|
||||||
|
|
||||||
|
<!-- PDF Preview -->
|
||||||
|
<div id="pdf-preview-container" class="hidden">
|
||||||
|
<h4>PDF Preview - Page <span id="preview-page-num">1</span></h4>
|
||||||
|
<img id="pdf-preview-image" src="" alt="PDF Preview">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tab-description">
|
<div class="tab-description">
|
||||||
<strong>Analysis Process:</strong>
|
<strong>Analysis Process:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,33 @@ const generatedOutputs = {
|
||||||
extractor: false
|
extractor: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Load and display PDF preview
|
||||||
|
function loadPDFPreview() {
|
||||||
|
const pdfFile = document.getElementById('pdf_file').value;
|
||||||
|
const pageNum = document.getElementById('page_num').value;
|
||||||
|
|
||||||
|
if (!pdfFile) {
|
||||||
|
document.getElementById('pdf-preview-container').classList.add('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update page number display
|
||||||
|
document.getElementById('preview-page-num').textContent = pageNum;
|
||||||
|
|
||||||
|
// Load the preview image
|
||||||
|
const previewImg = document.getElementById('pdf-preview-image');
|
||||||
|
previewImg.src = `/pdf-preview/${encodeURIComponent(pdfFile)}/${pageNum}`;
|
||||||
|
|
||||||
|
// Show the preview container
|
||||||
|
document.getElementById('pdf-preview-container').classList.remove('hidden');
|
||||||
|
|
||||||
|
// Handle loading errors
|
||||||
|
previewImg.onerror = function() {
|
||||||
|
this.alt = 'Failed to load PDF preview';
|
||||||
|
console.error('Failed to load PDF preview');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Tab switching functionality
|
// Tab switching functionality
|
||||||
function switchTab(tabName) {
|
function switchTab(tabName) {
|
||||||
// Hide all tab contents
|
// Hide all tab contents
|
||||||
|
|
@ -25,7 +52,10 @@ function switchTab(tabName) {
|
||||||
event.target.classList.add('active');
|
event.target.classList.add('active');
|
||||||
|
|
||||||
// Show previously generated content when switching tabs
|
// Show previously generated content when switching tabs
|
||||||
if (tabName === 'visualizer' && generatedOutputs.visualizer) {
|
if (tabName === 'analyzer') {
|
||||||
|
// Load PDF preview if a PDF is selected
|
||||||
|
loadPDFPreview();
|
||||||
|
} else if (tabName === 'visualizer' && generatedOutputs.visualizer) {
|
||||||
document.getElementById('result-image').src = generatedOutputs.visualizer + '?t=' + new Date().getTime();
|
document.getElementById('result-image').src = generatedOutputs.visualizer + '?t=' + new Date().getTime();
|
||||||
document.getElementById('image-container').classList.remove('hidden');
|
document.getElementById('image-container').classList.remove('hidden');
|
||||||
} else if (tabName === 'extractor' && generatedOutputs.extractor) {
|
} else if (tabName === 'extractor' && generatedOutputs.extractor) {
|
||||||
|
|
@ -186,6 +216,10 @@ window.addEventListener('DOMContentLoaded', function() {
|
||||||
pdfStatus.innerHTML = '<span class="error">Error: ' + error.message + '</span>';
|
pdfStatus.innerHTML = '<span class="error">Error: ' + error.message + '</span>';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add event listeners for PDF selection and page number changes
|
||||||
|
document.getElementById('pdf_file').addEventListener('change', loadPDFPreview);
|
||||||
|
document.getElementById('page_num').addEventListener('change', loadPDFPreview);
|
||||||
|
|
||||||
// Run an environment check on startup
|
// Run an environment check on startup
|
||||||
checkEnvironment();
|
checkEnvironment();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,31 @@ button:disabled {
|
||||||
box-shadow: var(--shadow-md);
|
box-shadow: var(--shadow-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PDF Preview container */
|
||||||
|
#pdf-preview-container {
|
||||||
|
margin-top: var(--spacing-lg);
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--spacing-lg);
|
||||||
|
background: var(--surface-light);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
border: 1px solid var(--border-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pdf-preview-container h4 {
|
||||||
|
color: var(--primary-dark);
|
||||||
|
margin: 0 0 var(--spacing-md) 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pdf-preview-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 600px;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
/* Extracted Images Gallery */
|
/* Extracted Images Gallery */
|
||||||
#extracted-images-container {
|
#extracted-images-container {
|
||||||
margin-top: var(--spacing-lg);
|
margin-top: var(--spacing-lg);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue