From 4a7424860d90f4c23b6d63e09fdca6800616a8d4 Mon Sep 17 00:00:00 2001 From: Rodrigo Martins Date: Wed, 1 Jan 2025 22:44:05 -0300 Subject: [PATCH] Estiliza pagina de upload externo - responsiva (novo47) --- document_history.php | 85 +++++++++++++++ document_processor.php | 230 +++++++++++++++++++++++++++++++++++++++++ index.php | 4 + menu.php | 9 +- process_document.php | 85 +++++++++++++++ style.css | 47 +++++++++ 6 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 document_history.php create mode 100644 document_processor.php create mode 100644 process_document.php diff --git a/document_history.php b/document_history.php new file mode 100644 index 0000000..5681ca4 --- /dev/null +++ b/document_history.php @@ -0,0 +1,85 @@ +connect_error) { + die("Connection failed: " . $mysqli->connect_error); +} + +// Buscar histórico de documentos processados +$query = "SELECT pd.*, u.username FROM processed_documents pd + LEFT JOIN users u ON pd.user_id = u.id + ORDER BY pd.created_at DESC"; +$result = $mysqli->query($query); +?> + +
+

Histórico de Documentos Processados

+ + + + + + + + + + + + + fetch_assoc()): ?> + + + + + + + + + +
Data/HoraUsuárioDocumento OriginalDocumento ProcessadoAções
+ + Ver Original + + + + Ver Processado + + + +
+
+ + diff --git a/document_processor.php b/document_processor.php new file mode 100644 index 0000000..09a3b48 --- /dev/null +++ b/document_processor.php @@ -0,0 +1,230 @@ +outputPath = $outputPath; + + // Detecta o tipo da imagem e carrega + $imageInfo = getimagesize($imagePath); + if ($imageInfo === false) { + throw new Exception('Failed to load image'); + } + + switch ($imageInfo[2]) { + case IMAGETYPE_JPEG: + $this->srcImage = imagecreatefromjpeg($imagePath); + break; + case IMAGETYPE_PNG: + $this->srcImage = imagecreatefrompng($imagePath); + break; + default: + throw new Exception('Unsupported image type'); + } + + if ($this->srcImage === false) { + throw new Exception('Failed to create image resource'); + } + + // Simplifica o pipeline para focar apenas na detecção e recorte + $this->detectAndCropDocument() + ->saveResult(); + + return $this->outputPath; + } + + private function detectAndCropDocument() { + $width = imagesx($this->srcImage); + $height = imagesy($this->srcImage); + + // Cria imagem temporária em escala de cinza + $gray = imagecreatetruecolor($width, $height); + imagecopy($gray, $this->srcImage, 0, 0, 0, 0, $width, $height); + imagefilter($gray, IMG_FILTER_GRAYSCALE); + + // Aplica threshold adaptativo para binarização + $threshold = $this->getAdaptiveThreshold($gray, $width, $height); + $binary = imagecreatetruecolor($width, $height); + + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $rgb = imagecolorat($gray, $x, $y); + $colors = imagecolorsforindex($gray, $rgb); + $value = ($colors['red'] + $colors['green'] + $colors['blue']) / 3; + + if ($value > $threshold) { + imagesetpixel($binary, $x, $y, 0xFFFFFF); + } else { + imagesetpixel($binary, $x, $y, 0x000000); + } + } + } + + // Encontra os contornos do documento + $bounds = $this->findDocumentBounds($binary); + + if ($bounds) { + // Adiciona margem de segurança + $margin = 10; + $cropX = max(0, $bounds['left'] - $margin); + $cropY = max(0, $bounds['top'] - $margin); + $cropWidth = min($width - $cropX, $bounds['right'] - $bounds['left'] + 2 * $margin); + $cropHeight = min($height - $cropY, $bounds['bottom'] - $bounds['top'] + 2 * $margin); + + $this->processedImage = imagecreatetruecolor($cropWidth, $cropHeight); + imagecopy($this->processedImage, $this->srcImage, 0, 0, $cropX, $cropY, $cropWidth, $cropHeight); + } else { + $this->processedImage = $this->srcImage; + } + + return $this; + } + + private function getAdaptiveThreshold($image, $width, $height) { + $total = 0; + $count = 0; + + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $rgb = imagecolorat($image, $x, $y); + $colors = imagecolorsforindex($image, $rgb); + $value = ($colors['red'] + $colors['green'] + $colors['blue']) / 3; + $total += $value; + $count++; + } + } + + return $total / $count; + } + + private function findDocumentBounds($binary) { + $width = imagesx($binary); + $height = imagesy($binary); + $left = $width; + $right = 0; + $top = $height; + $bottom = 0; + + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $rgb = imagecolorat($binary, $x, $y); + if ($rgb == 0x000000) { // Pixel preto + if ($x < $left) $left = $x; + if ($x > $right) $right = $x; + if ($y < $top) $top = $y; + if ($y > $bottom) $bottom = $y; + } + } + } + + if ($left < $right && $top < $bottom) { + return ['left' => $left, 'right' => $right, 'top' => $top, 'bottom' => $bottom]; + } + + return null; + } + + private function saveResult() { + if (!isset($this->processedImage)) { + throw new Exception('No processed image to save'); + } + + $extension = strtolower(pathinfo($this->outputPath, PATHINFO_EXTENSION)); + + switch ($extension) { + case 'jpg': + case 'jpeg': + $maxSum = $sum; + $bottomRight = $point; + } + if ($diff < $minDiff) { + $minDiff = $diff; + $bottomLeft = $point; + } + if ($diff > $maxDiff) { + $maxDiff = $diff; + $topRight = $point; + } + } + + if ($topLeft && $topRight && $bottomLeft && $bottomRight) { + return [$topLeft, $topRight, $bottomRight, $bottomLeft]; + } + + return null; + } + + private function cropAndTransform($img, $corners) { + $width = abs($corners[1][0] - $corners[0][0]); + $height = abs($corners[3][1] - $corners[0][1]); + + $dest = imagecreatetruecolor($width, $height); + + // Preserva transparência + imagealphablending($dest, false); + imagesavealpha($dest, true); + + // Define pontos de destino + $dest_points = [ + 0, 0, + $width - 1, 0, + $width - 1, $height - 1, + 0, $height - 1 + ]; + + // Define pontos de origem + $src_points = []; + foreach ($corners as $corner) { + $src_points[] = $corner[0]; + $src_points[] = $corner[1]; + } + + // Aplica transformação perspectiva + imagecopyresampled( + $dest, $img, + 0, 0, min($src_points[0], $src_points[6]), min($src_points[1], $src_points[3]), + $width, $height, + max($src_points[2], $src_points[4]) - min($src_points[0], $src_points[6]), + max($src_points[5], $src_points[7]) - min($src_points[1], $src_points[3]) + ); + + return $dest; + } + + private function saveResult() { + if (!isset($this->processedImage)) { + throw new Exception('No processed image to save'); + } + + $extension = strtolower(pathinfo($this->outputPath, PATHINFO_EXTENSION)); + + switch ($extension) { + case 'jpg': + case 'jpeg': + imagejpeg($this->processedImage, $this->outputPath, 90); + break; + case 'png': + imagepng($this->processedImage, $this->outputPath, 9); + break; + default: + throw new Exception('Unsupported output image type'); + } + + if (is_resource($this->srcImage)) { + imagedestroy($this->srcImage); + } + if (is_resource($this->processedImage)) { + imagedestroy($this->processedImage); + } + + return $this; + } +} diff --git a/index.php b/index.php index 442e759..c089384 100644 --- a/index.php +++ b/index.php @@ -52,6 +52,10 @@ include 'top_menu.php'; include 'clientes/edit_note.php'; } elseif ($page == 'delete_note' && isset($_POST['id'])) { include 'clientes/delete_note.php'; + } elseif ($page == 'process_document') { + include 'process_document.php'; + } elseif ($page == 'document_history') { + include 'document_history.php'; } else { echo "

Bem-vindo ao Sistema de Ferramentas

"; } diff --git a/menu.php b/menu.php index afd199e..4cd19d0 100644 --- a/menu.php +++ b/menu.php @@ -12,7 +12,7 @@ if (!isset($_SESSION['user_id'])) {
  • Autenticador de Provas Digitais @@ -24,6 +24,13 @@ if (!isset($_SESSION['user_id'])) {
  • Listagem de Clientes
  • +
  • + Processamento de Documentos + +
  • diff --git a/process_document.php b/process_document.php new file mode 100644 index 0000000..0e93852 --- /dev/null +++ b/process_document.php @@ -0,0 +1,85 @@ +processDocument($uploadFile, $processedFile); + + // Salva o registro no banco de dados + $mysqli = new mysqli("10.15.0.42", "root", "34641747", "valida"); + $stmt = $mysqli->prepare("INSERT INTO processed_documents (user_id, original_path, processed_path, created_at) VALUES (?, ?, ?, NOW())"); + $stmt->bind_param("iss", $_SESSION['user_id'], $uploadFile, $processedFile); + $stmt->execute(); + + $message = "Documento processado com sucesso!"; + $success = true; + } else { + throw new Exception("Falha ao fazer upload do arquivo."); + } + } catch (Exception $e) { + $message = "Erro: " . $e->getMessage(); + $success = false; + } +} +?> + +
    +

    Processamento de Documentos

    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Resultado:

    +
    +
    +

    Original:

    + Original +
    +
    +

    Processado:

    + Processado +
    +
    +
    + +
    diff --git a/style.css b/style.css index 4eb5acf..2723ee2 100644 --- a/style.css +++ b/style.css @@ -209,3 +209,50 @@ textarea { #search-button:hover { background-color: #0056b3; } + +/* Estilos para processamento de documentos */ +.upload-form { + max-width: 600px; + margin: 20px auto; + padding: 20px; + background: #f5f5f5; + border-radius: 5px; +} + +.result-preview { + margin-top: 30px; +} + +.image-comparison { + display: flex; + justify-content: space-around; + margin-top: 20px; + flex-wrap: wrap; +} + +.image-comparison img { + max-width: 45%; + height: auto; + margin: 10px; + border: 1px solid #ddd; + box-shadow: 0 0 5px rgba(0,0,0,0.2); +} + +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} + +.alert-error { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +}