Objectivo
El formato PGM es una de las versiones de los formatos de imagen NetPBM. En concreto, es la variante capaz de manejar imágenes en tonos de gris.
Su encabezado comienza con una línea que contiene P2 (si los datos de la imagen están en ASCII) o P5 (si está en binario).
La segunda línea contiene el ancho y el alto, separados por un espacio.
Una tercera línea contiene el valor de intensidad que corresponde al objetivo (típicamente 255, aunque también podría ser 15 u otro valor).
A partir de ahí comienzan los colores (tonos de gris) de los puntos que componen la imagen. En formato ASCII (P2) son números del 0 al 255 separados por espacios y quizás nuevas líneas. En formato binario (P5), son bytes contiguos, de 0 (negro) a 255 (blanco).
Debe crear un programa capaz de leer un archivo en formato binario PGM (encabezado P5), sin comentarios, con 255 tonos de gris (pero con un ancho y alto que pueden variar). Además, debe representar los colores (tonos de gris) en la consola de la siguiente manera:
• Si la intensidad del gris es superior a 200, dibujará un espacio en blanco.
• Si está entre 150 y 199, sacarás un punto.
• Si está entre 100 y 149, dibujarás un guión (-).
• Si está entre 50 y 99, dibujarás un símbolo "igual" (=).
• Si está entre 0 y 49, dibujarás un signo de libra (#).
El nombre del archivo que se va a analizar debe leerse desde la línea de comandos, no debe ser solicitado por el usuario ni preestablecido.
Nota: los saltos de línea (\ n) están representados por el carácter 10 del código ASCII (0x0A)
Ejemplo Ejercicio C#
Mostrar Código C#
// Importing the System namespace to use its classes
using System;
using System.IO; // Importing the IO namespace to handle file operations
class PgmViewer
{
// The main method, where the program execution begins
static void Main(string[] args)
{
// Check if a file name has been provided as a command-line argument
if (args.Length < 1)
{
// Display an error message if no file name is provided
Console.WriteLine("You must provide a PGM file as an argument.");
return; // Exit the program if no file is provided
}
// Retrieve the file name from the command-line arguments
string fileName = args[0];
try
{
// Read the entire PGM file into a byte array
byte[] pgmData = File.ReadAllBytes(fileName);
// Check if the file begins with "P5" to ensure it's a binary PGM file
if (pgmData[0] != 'P' || pgmData[1] != '5')
{
// Display an error message if the file is not in PGM binary format
Console.WriteLine("The file is not a binary PGM (P5) file.");
return; // Exit the program if the format is incorrect
}
// Set the offset to start reading the header after "P5"
int offset = 2; // Skip the first two characters "P5"
// Read the image width and height, skipping spaces or newlines
while (pgmData[offset] == 10 || pgmData[offset] == 32) offset++; // Skip spaces and newlines
int width = 0, height = 0; // Initialize width and height of the image
while (pgmData[offset] >= 48 && pgmData[offset] <= 57) width = width * 10 + (pgmData[offset++] - 48); // Read width (digits)
while (pgmData[offset] == 32) offset++; // Skip the space between width and height
while (pgmData[offset] >= 48 && pgmData[offset] <= 57) height = height * 10 + (pgmData[offset++] - 48); // Read height (digits)
// Skip spaces or newlines before reading the max pixel value
while (pgmData[offset] == 10 || pgmData[offset] == 32) offset++; // Skip spaces and newlines
int maxValue = 0; // Initialize the max intensity value (typically 255)
while (pgmData[offset] >= 48 && pgmData[offset] <= 57) maxValue = maxValue * 10 + (pgmData[offset++] - 48); // Read the max value (digits)
// The image data starts after the header, so we copy it to a separate array
byte[] pixelData = new byte[width * height]; // Allocate space for the pixel data
Array.Copy(pgmData, offset, pixelData, 0, pixelData.Length); // Copy the pixel data into the array
// Now we process and display the pixel data in the console
for (int i = 0; i < pixelData.Length; i++)
{
int intensity = pixelData[i]; // Get the intensity value for the current pixel
// Determine the character to print based on the intensity value
char displayChar = intensity > 200 ? ' ' : // If intensity is greater than 200, print a space
(intensity >= 150) ? '.' : // If intensity is between 150 and 199, print a dot
(intensity >= 100) ? '-' : // If intensity is between 100 and 149, print a dash
(intensity >= 50) ? '=' : // If intensity is between 50 and 99, print an equals sign
'#'; // If intensity is between 0 and 49, print a hash sign
// Print the character for the current pixel
Console.Write(displayChar);
// If we've reached the end of a row, print a new line
if ((i + 1) % width == 0)
{
Console.WriteLine(); // Move to the next line after each row of pixels
}
}
}
catch (Exception ex)
{
// Display an error message if an exception occurs during file processing
Console.WriteLine($"Error processing the file: {ex.Message}");
}
}
}
Salida
PGM file (image.pgm), containing a binary PGM image in the following format:
P5
4 4
255
255 255 255 0 0 0 255 255 255 0 0 0 255 255 255 0
When the program processes the above file, it will display something like this in the console:
####
==.
. .
.
Console Message:
Image data has been processed and displayed in the console.
If the file format or content is incorrect (e.g., not a valid binary PGM file), an error message is shown:
The file is not a binary PGM (P5) file.
Or if an exception occurs (e.g., file not found, read/write error), it will display:
Error processing the file: error message
Código de Ejemplo Copiado!
Comparte este Ejercicio C# Sharp