PDI+VC · Exercício de Programação

EP01_10 — 📄 Metadados: Leitura de Arquivo PGM

1.17.10 EP01_10 📄 Metadados: Leitura de Arquivo PGM

Nesta atividade, você deve ler um arquivo de imagem no formato PGM (Portable Gray Map) e extrair suas dimensões a partir do cabeçalho.

  • O formato PGM (P2) é um arquivo de texto simples (ASCII) que armazena imagens em tons de cinza.
  • O arquivo possui um cabeçalho estruturado da seguinte forma:
  1. Versão: O identificador P2.
  2. Comentários: Linhas opcionais que começam com # (devem ser ignoradas).
  3. Dimensões: Dois inteiros representando Largura e Altura.
  4. Máximo: Um inteiro representando a intensidade máxima (geralmente 255).
  • Após o cabeçalho, seguem-se os dados dos pixels.

📌 Importante:

  • Leitura de Arquivo: Você deve abrir o arquivo indicado no exemplo utilizando a função open() do Python.
  • Ordem de Saída: Ao contrário da ordem presente no arquivo, a saída esperada deve estar no formato de tupla: (Altura, Largura, Canais).
  • Como arquivos PGM são em tons de cinza, o número de Canais é sempre 1.
  • Ver um simulador interativo para esta questão na Figura 1.20 (ajuste as dimensões para ver como o cabeçalho ASCII é gerado).

1.17.10.1 🧠 Entendendo o formato PGM

O formato PGM é um dos mais simples para processamento de imagens. Por ser em texto puro, ele permite visualizar os metadados e até os valores dos pixels abrindo o arquivo em um bloco de notas:

Componente Exemplo Significado
Magic Number P2 Identifica que é um PGM em formato de texto (ASCII).
Comentário # CREATOR... Linha informativa ignorada pelo processador.
Dimensões 397 343 397 colunas (Largura) e 343 linhas (Altura).
Intensidade 255 Define o valor do branco puro (escala de 0 a 255).

1.17.10.2 📋 Tarefa (especificação para VPL)

Entrada:

Nenhuma entrada via teclado. O programa deve ler o arquivo "aula01fig03b.pgm" presente no diretório de execução.

Saída:

Uma tupla contendo (Altura, Largura, 1).

1.17.10.3 📌 Exemplos

Nome do Arquivo Saída Esperada Observação
“aula01fig03b.pgm” (343, 397, 1) Note a inversão da ordem: Altura primeiro
📄 Simulador EP01_10: Estrutura do Arquivo PGM ASCII P2 & Format (H, W, C)

Altere as dimensões de largura (W) e altura (H) para observar a montagem dinâmica do cabeçalho PGM e o formato da tupla do array resultante em Python (Linhas × Colunas × Canais).

DEFINIÇÕES DA IMAGEM
💡 Atenção à convenção: O cabeçalho PGM declara primeiramente W H (Largura × Altura), enquanto o array em Python/NumPy reporta a tupla como (H, W, C) (Linhas × Colunas × Canais).
CONTEÚDO DO ARQUIVO (.PGM)
P2
# CREATOR: UFABC PDI / EP01_10
397 343
255
120 134 210 0 85 255 ...
Saída da Função mm.readImg (Formato do Array):
(343, 397, 1)
Figura 1.20: Simulador EP01_10: Estrutura de Arquivo PGM (Cabeçalho ASCII P2 e Mapeamento para Tupla Python)
NotaNota

O arquivo necessário para este EP será baixado automaticamente do repositório por meio do seguinte código:

%%writefile tmp/mm_out_2.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <sys/stat.h>

// Função para verificar se um arquivo existe
bool fileExists(const std::string& filename) {
    struct stat buffer;
    return (stat(filename.c_str(), &buffer) == 0);
}

// Função para baixar um arquivo usando curl (substituto de urllib.request)
int downloadFile(const std::string& url, const std::string& filename) {
    std::string command = "curl -s -o " + filename + " -A 'Mozilla/5.0' " + url;
    return system(command.c_str());
}

int main() {
    const std::string BASE_URL = "https://raw.githubusercontent.com/fzampirolli/pdi-vc/master/all/cap01/imagens";
    const std::string file = "aula01fig03b.pgm";

    std::string files[] = {file};

    for (const auto& f : files) {
        if (!fileExists(f)) {
            std::string url = BASE_URL + "/" + f;
            int result = downloadFile(url, f);

            if (result == 0) {
                std::cout << "✅ Arquivo baixado: " << f << std::endl;
            } else {
                std::cerr << "❌ Erro: Não foi possível baixar de " << url << std::endl;
            }
        }
    }

    return 0;
}
Overwriting tmp/mm_out_2.cpp
!g++ -I. -std=c++17 tmp/mm_out_2.cpp -o tmp/mm_out_2 \
  && ./tmp/mm_out_2
%%writefile EP01_10.cpp
// sua solução
Overwriting EP01_10.cpp
TestSuite("EP01_10.cpp").run()
✔️ EP01_10.cases já existe em casos/
📋 1 caso(s) carregado(s) de casos/EP01_10.cases

🔍 Testando C++: EP01_10.cpp
⚠️ EP01_10.cpp: Arquivo sem conteúdo (menos de 3 linhas). Testes ignorados.