From b4db34fda3b941ab2e5e0c814e66c6f3da711e24 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Wed, 26 Jan 2022 17:38:42 +0100 Subject: [PATCH] removed subdirectories --- .gitignore | 4 +- include/bild.hpp | 102 ------------------------ src/bild.cpp | 183 -------------------------------------------- src/edgedetect.cpp | 48 ------------ src/imageviewer.cpp | 42 ---------- src/smooth.cpp | 53 ------------- 6 files changed, 3 insertions(+), 429 deletions(-) delete mode 100644 include/bild.hpp delete mode 100644 src/bild.cpp delete mode 100644 src/edgedetect.cpp delete mode 100644 src/imageviewer.cpp delete mode 100644 src/smooth.cpp diff --git a/.gitignore b/.gitignore index b497ff1..786131b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ bin/ -.vscode/ \ No newline at end of file +html/ +latex/ +.vscode/ diff --git a/include/bild.hpp b/include/bild.hpp deleted file mode 100644 index 8fb5006..0000000 --- a/include/bild.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -/** - * @brief Stores PGM image data - * - * This class can read and write PGM images, perform smoothing and - * edge detection on them and display them in the console as ASCII art - */ -class Bild -{ -public: - // ASCII characters used when printing the image to stdout - static const std::string asciiBrightnessMap; - -public: - /** - * @brief Creates a new empty picture. - * - * The created picture has no dimensions and contains no pixel data. - */ - Bild() = default; - - /** - * @brief Construct a new empty picture with meta data - * - * The pixel buffer will be empty, but the meta data (width, height, description) - * will be set, and the pixel buffer will be resized to match the dimensions - * - * @param width Width of the image - * @param height Height of the image - * @param description Description of the image - */ - Bild(uint32_t width, uint32_t height, const std::string& description); - - /** - * @brief Copy an image - * - * The copy will copy the image data from the original image to a new buffer - * - * @param other The image to copy from - */ - Bild(const Bild& other) = default; - - /** - * @brief Load an image - * - * Reads a file containing image data and populates the pixel array - * - * @param file (Valid) filestream containing image data - * @param image The image object to store the data in - * @return The modified filestream - */ - friend std::ifstream& operator>>(std::ifstream& file, Bild& image); - - /** - * @brief Save an image - * - * Writes the stored image data into a file, overwriting any contents in it - * - * @param file (Valid) filestream to store the image in - * @param image The image object to get the data from - * @return The modified filestream - */ - friend std::ofstream& operator<<(std::ofstream& file, const Bild& image); - - /** - * @brief Renders the image to the console - * - * Draws the image in the console using ascii characters. - * Das war zwar in der Aufgabe nicht verlangt aber ich wollte gern die Bilder sehen - * - * @param os Output stream to draw to - * @param image Image to draw - * @return The modified output stream - */ - friend std::ostream& operator<<(std::ostream& os, const Bild& image); - - /** - * @brief Applies smoothing to an image, effectively blurring it - * - * @return The blurred image - */ - Bild Geglaettet() const; - - /** - * @brief Performs edge detection on the image - * - * @return An image with only the edges found in the original - */ - Bild Kantenbild() const; - -private: - uint32_t width {}; - uint32_t height {}; - std::string description; - std::vector pixels; -}; diff --git a/src/bild.cpp b/src/bild.cpp deleted file mode 100644 index 4c37518..0000000 --- a/src/bild.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "bild.hpp" - -#include -#include - -const std::string Bild::asciiBrightnessMap = ".'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; - -Bild::Bild(uint32_t width, uint32_t height, const std::string& description) : - width(width), height(height), description(description) -{ - pixels.resize(width * height); -} - -std::ifstream& operator>>(std::ifstream& file, Bild& image) -{ - std::string lineContent; - - // First line should contain "P2" - std::getline(file, lineContent); - if(lineContent[0] != 'P' || lineContent[1] != '2') - { - throw std::runtime_error("Missing/Wrong PGM magic number."); - } - - // The second line contains an image description - std::getline(file, lineContent); - std::string::iterator it; - for(it = lineContent.begin(); it != lineContent.end(); it++) // Flush out any leading spaces to get the description - { - if(*it != ' ' && *it != '#') // Break from loop if the iterator reached a character that isnt '#' or ' ' - break; - } - - image.description = std::string(it, lineContent.end() - 1); // Store the description (and cut off the newline) - - // The third line contains the image dimensions - file >> image.width >> image.height; - std::getline(file, lineContent); - - // The fourth line contains the max brightness value - std::getline(file, lineContent); // Do nothing with it - - // The remaining file contains image data - uint16_t pixelValue = 0; - while(std::getline(file, lineContent)) // Loop through remaining lines - { - std::stringstream ss(lineContent); - while(ss >> pixelValue) // Loop through numbers in the line - { - image.pixels.push_back(static_cast(pixelValue)); // Write pixel into the array - } - } - - // Check if vector size matches image dimensions - if(image.pixels.size() != static_cast(image.width) * image.height) - { - throw std::runtime_error( - "Amount of image data doesn't match image dimensions. Expected " + - std::to_string(image.width * image.height) + - " pixels, got " + std::to_string(image.pixels.size()) + - " pixels instead." - ); - } - - return file; -} - -std::ofstream& operator<<(std::ofstream& file, const Bild& image) -{ - file << "P2" << std::endl; // Write magic number to file - file << "# " << image.description << std::endl; // Write image description - file << image.width << " " << image.height << std::endl; // Write image dimensions - file << 255 << std::endl; // Write max brightness value - - // Write pixel data - std::string line; - for(uint8_t pixel : image.pixels) - { - uint32_t value = static_cast(pixel); - // If the current line would become longer than 70 characters, write the line to - // the file, insert a newline and clear the line - if(line.size() + std::to_string(value).length() > 70) - { - file << line << std::endl; - line.clear(); - } - - line += std::to_string(value) + " "; - } - - // Write remaining lines to file - file << line << std::endl; - - return file; -} - -std::ostream& operator<<(std::ostream& os, const Bild& image) -{ - // Loop over pixels in image - for(uint16_t y = 0; y < image.height; y++) - { - std::stringstream lineBuffer; - for(uint16_t x = 0; x < image.width; x++) - { - uint8_t brightness = image.pixels[y * image.width + x]; - - // Map the pixel brightness (which is in the interval [0, 255]) to the ascii chart length - uint8_t asciiMapIndex = static_cast(brightness * (Bild::asciiBrightnessMap.length() - 1) / 255); - lineBuffer << Bild::asciiBrightnessMap[asciiMapIndex]; - } - - std::cout << lineBuffer.str() << std::endl; - } - - return os; -} - -Bild Bild::Geglaettet() const -{ - // Create new image with same dimensions - Bild smoothedImage(width, height, description + " smoothed"); - - // Apply smoothing - for(uint32_t y = 0; y < smoothedImage.height; y++) - { - for(uint32_t x = 0; x < smoothedImage.width; x++) - { - // If this is a border pixel just copy it from the original - if(y == 0 || x == 0 || y == smoothedImage.height - 1 || x == smoothedImage.width - 1) - { - smoothedImage.pixels[y * smoothedImage.width + x] = pixels[y * smoothedImage.width + x]; - continue; - } - - // Else, make this pixel the average of its 4 neighbours - uint32_t sumOfPixels = - pixels[(y - 1) * smoothedImage.width + (x + 0)] + - pixels[(y + 1) * smoothedImage.width + (x + 0)] + - pixels[(y + 0) * smoothedImage.width + (x - 1)] + - pixels[(y + 0) * smoothedImage.width + (x + 1)] + - 4 * pixels[y * smoothedImage.width + x]; - - smoothedImage.pixels[y * smoothedImage.width + x] = static_cast(sumOfPixels / 8); - } - } - - return smoothedImage; -} - -Bild Bild::Kantenbild() const -{ - // Create new image and copy metadata - Bild modifiedImage(width, height, description + " edged"); - - // Apply edge detection - for(uint32_t y = 0; y < modifiedImage.height; y++) - { - for(uint32_t x = 0; x < modifiedImage.width; x++) - { - // If this is a border pixel set its brightness to 0 - if(y == 0 || x == 0 || y == modifiedImage.height - 1 || x == modifiedImage.width - 1) - { - modifiedImage.pixels[y * modifiedImage.width + x] = 0; - continue; - } - - // Else, apply the formula to calculate pixel brightness - int32_t sumOfPixels = - pixels[(y - 1) * modifiedImage.width + (x + 0)] + - pixels[(y + 1) * modifiedImage.width + (x + 0)] + - pixels[(y + 0) * modifiedImage.width + (x - 1)] + - pixels[(y + 0) * modifiedImage.width + (x + 1)] - - 4 * pixels[y * modifiedImage.width + x]; - - if(sumOfPixels < 0) - sumOfPixels = 0; - - modifiedImage.pixels[y * modifiedImage.width + x] = static_cast(sumOfPixels / 8); - } - } - - return modifiedImage; -} diff --git a/src/edgedetect.cpp b/src/edgedetect.cpp deleted file mode 100644 index a095d56..0000000 --- a/src/edgedetect.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Reads a PGM file and performs edge detection, then writes the result to disk - */ -#include -#include "bild.hpp" - -int main(int argc, char** argv) -{ - if(argc < 2) - { - std::cout << "Usage: edetect " << std::endl; - return 0; - } - std::string filename = argv[1]; - - // Load file - std::ifstream file(filename); - if(!file.good()) - { - std::cerr << "Failed to open file" << std::endl; - return -1; - } - - // Create image - Bild image; - try - { - file >> image; - } - catch(const std::runtime_error& err) - { - std::cerr << err.what() << std::endl; - file.close(); - return -1; - } - - file.close(); - - // Print image - image = image.Kantenbild(); - - filename.insert(filename.find('.'), "_modified"); - std::ofstream outFile(filename); - outFile << image; - outFile.close(); - - return 0; -} diff --git a/src/imageviewer.cpp b/src/imageviewer.cpp deleted file mode 100644 index 07760ad..0000000 --- a/src/imageviewer.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Displays a given PGM image in the console using ASCII characters - */ -#include -#include "bild.hpp" - -int main(int argc, char** argv) -{ - // If there are no additional arguments print usage info - if(argc < 2) - { - std::cout << "Usage: imageviewer " << std::endl; - return 0; - } - - // Load file - std::ifstream file(argv[1]); - if(!file.good()) - { - std::cerr << "Failed to open file" << std::endl; - return -1; - } - - // Create image - Bild image; - try - { - file >> image; - } - catch(const std::runtime_error& err) - { - std::cerr << err.what() << std::endl; - file.close(); - return -1; - } - - file.close(); - - // Print image - std::cout << image << std::endl; - return 0; -} diff --git a/src/smooth.cpp b/src/smooth.cpp deleted file mode 100644 index 6686320..0000000 --- a/src/smooth.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Reads a PGM image and smooths it by some amount, then writes it back to disk - */ -#include -#include "bild.hpp" - -int main(int argc, char** argv) -{ - if(argc < 2) - { - std::cout << "Usage: smooth " << std::endl; - return 0; - } - std::string filename = argv[1]; - - uint16_t smoothing; - std::cout << "Wie oft soll das Bild geglaettet werden? "; - std::cin >> smoothing; - - // Load file - std::ifstream file(filename); - if(!file.good()) - { - std::cerr << "Failed to open file" << std::endl; - return -1; - } - - // Create image - Bild image; - try - { - file >> image; - } - catch(const std::runtime_error& err) - { - std::cerr << err.what() << std::endl; - file.close(); - return -1; - } - - file.close(); - - // Print image - for(uint8_t i = 0; i < smoothing; i++) - image = image.Geglaettet(); - - filename.insert(filename.find('.'), "_modified"); - std::ofstream outFile(filename); - outFile << image; - outFile.close(); - - return 0; -}