Commit fc0133eb by Pedro Bueno

Ajuste nos arquivos

parent 996791ac
from flask import Flask, render_template, request, send_file, redirect
import fitz, os, zipfile, sqlite3
from flask import Flask, render_template, request, send_file
import io
import fitz # PyMuPDF
import os
import zipfile
from PIL import Image
import sqlite3
app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
# Configuração do Banco de Dados (CRUD)
def init_db():
conn = sqlite3.connect('database.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS configuracoes
(id INTEGER PRIMARY KEY AUTOINCREMENT, nome TEXT, coords TEXT)''')
conn.commit()
conn.execute('''CREATE TABLE IF NOT EXISTS configuracoes
(id INTEGER PRIMARY KEY AUTOINCREMENT, nome TEXT, coords TEXT)''')
conn.close()
@app.route('/')
......@@ -22,42 +23,59 @@ def index():
conn.close()
return render_template('index.html', configs=configs)
@app.route('/salvar', methods=['POST'])
def salvar_config():
nome = request.form['nome_config']
coords = request.form['coords']
conn = sqlite3.connect('database.db')
conn.execute('INSERT INTO configuracoes (nome, coords) VALUES (?, ?)', (nome, coords))
conn.commit()
conn.close()
return redirect('/')
@app.route('/upload_preview', methods=['POST'])
def upload_preview():
if 'pdf' not in request.files:
return {"error": "Sem arquivo"}, 400
pdf = request.files['pdf']
pdf_path = os.path.join(UPLOAD_FOLDER, pdf.filename)
pdf.save(pdf_path)
return {"filename": pdf.filename}
@app.route('/preview/<filename>/<int:pagnumber>')
def preview(filename, pagnumber):
pdf_path = os.path.join(UPLOAD_FOLDER, filename)
if not os.path.exists(pdf_path): return "Erro", 404
doc = fitz.open(pdf_path)
# Garante que a página solicitada existe no PDF
total = len(doc)
if pagnumber >= total: pagnumber = total - 1
if pagnumber < 0: pagnumber = 0
page = doc[pagnumber]
pix = page.get_pixmap(dpi=100)
img_data = pix.tobytes("png")
doc.close()
return send_file(io.BytesIO(img_data), mimetype='image/png')
@app.route('/processar', methods=['POST'])
def processar():
pdf = request.files['pdf']
filename = request.form['filename']
inicio = int(request.form['inicio'])
fim = int(request.form['fim'])
coords = list(map(float, request.form['coords'].split(',')))
pdf_path = os.path.join(UPLOAD_FOLDER, pdf.filename)
pdf.save(pdf_path)
c = list(map(float, request.form['coords'].split(',')))
pdf_path = os.path.join(UPLOAD_FOLDER, filename)
doc = fitz.open(pdf_path)
zip_path = os.path.join(UPLOAD_FOLDER, "resultado.zip")
zip_path = os.path.join(UPLOAD_FOLDER, "recortes.zip")
with zipfile.ZipFile(zip_path, 'w') as zip_f:
for p in range(inicio, fim + 1):
if p >= len(doc): break
page = doc[p] # Lógica +1 integrada
pix = page.get_pixmap(dpi=300)
page = doc[p]
pix = page.get_pixmap(dpi=300)
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
fator = 300 / 72
area = (coords[0]*fator, coords[1]*fator, coords[2]*fator, coords[3]*fator)
s = 300 / 100 # Escala Preview vs Corte Final
area = (c[0]*s, c[1]*s, (c[0]+c[2])*s, (c[1]+c[3])*s)
img_cortada = img.crop(area)
img_tmp = f"pag_{p}.png"
img_cortada.save(img_tmp)
zip_f.write(img_tmp)
os.remove(img_tmp)
img_name = f"pagina_{p}.png"
img_path = os.path.join(UPLOAD_FOLDER, img_name)
img_cortada.save(img_path)
zip_f.write(img_path, img_name)
os.remove(img_path)
doc.close()
return send_file(zip_path, as_attachment=True)
......
body { background: #121212; color: #eee; font-family: sans-serif; display: flex; justify-content: center; padding: 50px; }
.container { background: #1e1e1e; padding: 30px; border-radius: 12px; width: 450px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); }
h1 { text-align: center; color: #4CAF50; }
input { width: 100%; padding: 10px; margin: 10px 0; background: #333; border: 1px solid #444; color: white; border-radius: 5px; box-sizing: border-box; }
.row { display: flex; gap: 10px; }
button { width: 100%; padding: 12px; background: #4CAF50; border: none; color: white; font-weight: bold; border-radius: 5px; cursor: pointer; margin-top: 10px; }
button:hover { background: #45a049; }
hr { border: 0; border-top: 1px solid #333; margin: 20px 0; }
.config-list { list-style: none; padding: 0; font-size: 14px; }
.config-list li { background: #252525; padding: 10px; margin-bottom: 5px; border-radius: 4px; }
.copyright { text-align: center; font-size: 10px; color: #666; margin-top: 20px; }
\ No newline at end of file
body { background: #121212; color: #eee; font-family: sans-serif; display: flex; justify-content: center; padding: 20px; }
.container { background: #1e1e1e; padding: 30px; border-radius: 15px; width: 100%; max-width: 700px; box-shadow: 0 10px 30px rgba(0,0,0,0.5); text-align: center; }
h1 { color: #4CAF50; }
.custom-file-upload { border: 2px dashed #4CAF50; padding: 20px; cursor: pointer; display: block; border-radius: 10px; background: #252525; margin-bottom: 20px; }
.row { display: flex; gap: 15px; margin-bottom: 20px; }
.input-group { flex: 1; text-align: left; }
input[type="number"] { width: 100%; padding: 10px; background: #333; border: 1px solid #444; color: white; border-radius: 5px; }
.btn-primary { width: 100%; padding: 15px; background: #4CAF50; border: none; color: white; font-weight: bold; border-radius: 8px; cursor: pointer; }
.footer { margin-top: 20px; font-size: 11px; color: #666; }
\ No newline at end of file
......@@ -2,40 +2,207 @@
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>PDF Supremo CRUD</title>
<title>PDF Visual - Pedro Bueno</title>
<link rel="stylesheet" href="/static/style.css">
<style>
#preview-container {
display: none;
margin: 20px auto;
text-align: center;
}
#preview-wrapper {
position: relative;
display: inline-block;
border: 2px solid #555;
line-height: 0;
overflow: hidden; /* Garante que nada saia visualmente */
user-select: none;
}
#pdf-img {
max-width: 100%;
display: block;
}
#selector {
position: absolute;
border: 2px dashed #4CAF50;
background: rgba(76, 175, 80, 0.2);
cursor: move;
box-sizing: border-box;
width: 150px;
height: 150px;
top: 0;
left: 0;
}
#resizer {
position: absolute;
right: 0;
bottom: 0;
width: 15px;
height: 15px;
background: #4CAF50;
cursor: nwse-resize;
}
.nav-controls {
margin: 15px 0;
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
}
.nav-btn {
background: #444;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
.nav-btn:hover { background: #555; }
</style>
</head>
<body>
<div class="container">
<h1>Manipulador de PDF 🚀</h1>
<form action="/processar" method="post" enctype="multipart/form-data">
<input type="file" name="pdf" required>
<h1>Recortador Visual 2.0 🚀</h1>
<label for="pdf-file" class="custom-file-upload">
📁 Selecionar PDF para Visualização
</label>
<input type="file" id="pdf-file" accept="application/pdf" onchange="uploadAndPreview()" style="display:none;">
<div id="loading" style="display:none; color: #4CAF50;">⏳ Carregando página...</div>
<div id="preview-container">
<div class="nav-controls">
<button type="button" class="nav-btn" onclick="changePage(-1)">⬅️ Anterior</button>
<span id="page-info">Página: 0</span>
<button type="button" class="nav-btn" onclick="changePage(1)">Próxima ➡️</button>
</div>
<div id="preview-wrapper">
<img id="pdf-img">
<div id="selector">
<div id="resizer"></div>
</div>
</div>
</div>
<form action="/processar" method="post" id="main-form">
<input type="hidden" name="filename" id="hidden-filename">
<input type="hidden" name="coords" id="coords-input">
<div class="row">
<input type="number" name="inicio" placeholder="Início" value="10">
<input type="number" name="fim" placeholder="Fim" value="11">
<div class="input-group">
<label>Página Início:</label>
<input type="number" name="inicio" id="input-inicio" value="0">
</div>
<div class="input-group">
<label>Página Fim:</label>
<input type="number" name="fim" value="1">
</div>
</div>
<input type="text" name="coords" id="coords_input" placeholder="x0, y0, x1, y1" value="0, 51, 700, 745">
<button type="submit" class="btn-primary">GERAR ZIP</button>
<button type="submit" class="btn-primary">GERAR E BAIXAR ZIP</button>
</form>
<p class="footer">© Pedro Bueno</p>
</div>
<script>
const selector = document.getElementById('selector');
const resizer = document.getElementById('resizer');
const img = document.getElementById('pdf-img');
const coordsInput = document.getElementById('coords-input');
const inputInicio = document.getElementById('input-inicio');
let currentPage = 0;
<hr>
async function uploadAndPreview() {
const file = document.getElementById('pdf-file').files[0];
if(!file) return;
<h3>Salvar Configuração de Corte</h3>
<form action="/salvar" method="post">
<input type="text" name="nome_config" placeholder="Nome (Ex: Livro de História)">
<input type="text" name="coords" placeholder="Coordenadas">
<button type="submit">Salvar no Banco</button>
</form>
document.getElementById('loading').style.display = 'block';
const formData = new FormData();
formData.append('pdf', file);
<ul class="config-list">
{% for config in configs %}
<li>
<strong>{{ config[1] }}</strong>: {{ config[2] }}
</li>
{% endfor %}
</ul>
</div>
const res = await fetch('/upload_preview', { method: 'POST', body: formData });
const data = await res.json();
document.getElementById('hidden-filename').value = data.filename;
currentPage = parseInt(inputInicio.value) || 0;
updatePreview();
}
function updatePreview() {
const filename = document.getElementById('hidden-filename').value;
img.src = `/preview/${filename}/${currentPage}?t=${new Date().getTime()}`;
document.getElementById('page-info').innerText = `Visualizando Página: ${currentPage}`;
inputInicio.value = currentPage; // Sincroniza o form com a visão
img.onload = () => {
document.getElementById('loading').style.display = 'none';
document.getElementById('preview-container').style.display = 'block';
updateCoords();
};
}
function changePage(delta) {
currentPage += delta;
if (currentPage < 0) currentPage = 0;
updatePreview();
}
// Lógica de Arrastar e Redimensionar com Contenção
let isDragging = false, isResizing = false;
let startX, startY, startW, startH;
selector.onmousedown = (e) => {
if(e.target === resizer) return;
isDragging = true;
startX = e.clientX - selector.offsetLeft;
startY = e.clientY - selector.offsetTop;
};
resizer.onmousedown = (e) => {
isResizing = true;
startX = e.clientX;
startY = e.clientY;
startW = selector.offsetWidth;
startH = selector.offsetHeight;
e.stopPropagation();
e.preventDefault();
};
window.onmousemove = (e) => {
if (isDragging) {
let x = e.clientX - startX;
let y = e.clientY - startY;
// Bloqueia saída das bordas
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + selector.offsetWidth > img.offsetWidth) x = img.offsetWidth - selector.offsetWidth;
if (y + selector.offsetHeight > img.offsetHeight) y = img.offsetHeight - selector.offsetHeight;
selector.style.left = x + 'px';
selector.style.top = y + 'px';
}
if (isResizing) {
let newWidth = startW + (e.clientX - startX);
let newHeight = startH + (e.clientY - startY);
// Bloqueia redimensionamento para fora da imagem
if (selector.offsetLeft + newWidth > img.offsetWidth) newWidth = img.offsetWidth - selector.offsetLeft;
if (selector.offsetTop + newHeight > img.offsetHeight) newHeight = img.offsetHeight - selector.offsetTop;
selector.style.width = Math.max(20, newWidth) + 'px';
selector.style.height = Math.max(20, newHeight) + 'px';
}
updateCoords();
};
window.onmouseup = () => { isDragging = false; isResizing = false; };
function updateCoords() {
coordsInput.value = `${selector.offsetLeft},${selector.offsetTop},${selector.offsetWidth},${selector.offsetHeight}`;
}
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment