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
conn.execute('''CREATE TABLE IF NOT EXISTS configuracoes
(id INTEGER PRIMARY KEY AUTOINCREMENT, nome TEXT, coords TEXT)''')
conn.commit()
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
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>
<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">
<form action="/processar" method="post" enctype="multipart/form-data">
<input type="file" name="pdf" required>
<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>
<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>
</div>
<button type="submit" class="btn-primary">GERAR E BAIXAR ZIP</button>
</form>
<p class="footer">© Pedro Bueno</p>
</div>
<hr>
<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');
<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>
let currentPage = 0;
<ul class="config-list">
{% for config in configs %}
<li>
<strong>{{ config[1] }}</strong>: {{ config[2] }}
</li>
{% endfor %}
</ul>
async function uploadAndPreview() {
const file = document.getElementById('pdf-file').files[0];
if(!file) return;
</div>
document.getElementById('loading').style.display = 'block';
const formData = new FormData();
formData.append('pdf', file);
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