diff --git a/documents/references.md b/documents/references.md index 61cae162138f876da5d9f0dc23c9000c6af5961f..2107c290b00d65b69648cf2b7c55942f54766181 100644 --- a/documents/references.md +++ b/documents/references.md @@ -33,8 +33,11 @@ Various references used in project. ### C++ Classes <https://www.w3schools.com/cpp/cpp_classes.asp> -#### Files Compiling without "Standard" C++ Library Access -<https://stackoverflow.com/a/10271117> +### Structs Vs Classes in C++ +<https://stackoverflow.com/a/36917400> + +### Type Casting +<https://en.cppreference.com/w/cpp/language/static_cast> #### Reading In & Manipulating Image Files * <https://stackoverflow.com/a/59553786> @@ -53,6 +56,13 @@ Various references used in project. <https://cuda-tutorial.readthedocs.io/en/latest/tutorials/tutorial01/> +## General Errors + +#### Files Compiling without "Standard" C++ Library Access +<https://stackoverflow.com/a/10271117> + + + # c++ manipulate pixels in image diff --git a/part_1/main.cu b/part_1/main.cu index 2b357f2347a058980991aeda51553e0a0609d59f..8b9364e76e13f299a1ad13c1a98f98c1b84d2cc7 100644 --- a/part_1/main.cu +++ b/part_1/main.cu @@ -32,76 +32,213 @@ void process_file(std::string path_str); // Global Variables. + +/** + * Class that holds data for a single image. + */ class Image { + private: + /** + * Struct to act as a "container" of sorts for each individual rgb pixel. + * An array of these creates our entire image. + * + * According to https://stackoverflow.com/a/36917400, this is basically treated as a sub-class. + * This allows creating multiple constructors, which will handle different scenarios of pixel input. + */ + struct Rgb { + // Struct variables. + float r, g, b; + + /** + * Struct constructors. + * + * First one acts as a "default" that provides black pixels. + * When a single float is provided, the second constructor sets all three rgb channels to that value. + * Finally, when three floats are provided, the last constructor sets rgb channels accordingly. + */ + Rgb(): r(0), g(0), b(0) {} + Rgb(float c): r(c), g(c), b(c) {} + Rgb(float _r, float _g, float _b) : r(_r), g(_g), b(_b) {} + + }; + + // Private Variables. + std::string input_path; + std::string output_path; + unsigned int width; + unsigned int height; + int bit_depth; + Rgb *pixel_arr; // Array of pixel data. + + public: + // Public Variables. + static const Rgb pixelBlack, pixelWhite, pixelRed, pixelGreen, pixelBlue, pixelYellow, pixelPink, pixelLiBlue; + + + //region Constructors. + /** * Base constructor. */ Image() { - // printf("Constructing Image class."); - std::cout << "Constructing Image class." << std::endl; + // Currently test logic. + std::cout << "\nConstructing Image class." << std::endl; + + // Essentially creates a 10x10 pixel test image. + input_path = "../input/pbm/400x300/hallway_00.pbm"; + output_path = "../output/test_00.pbm"; + width = 10; + height = 10; + bit_depth = 255; + Rgb c = pixelBlack; // Default color. Can select based on below preset colors. + + // Create and populate image. + pixel_arr = new Rgb[width * height]; + for (int index = 0; index < (width * height); index++) { + pixel_arr[index] = c; + } + + std::cout << "Image class populated." << std::endl; } - // void test_method() { - // std::cout << "test_method() aaaa" << std::endl; - // } + /** + * Constructor that takes input path to image file. + * Output path is determined based on parsing input path. + */ + Image(char* user_path) { + std::cout << "\nConstructing Image class." << std::endl; - // public: - void test_method() { - std::cout << "Running test_method()" << std::endl; - std::cout << "test_method() finished" << std::endl; + // populate here + + std::cout << "Image class populated." << std::endl; + } + + //endregion Constructors. + + + //region Public Methods. + + /** + * Displays general properties of image held in class. + */ + void display_properties() { + std::cout << std::endl; + std::cout << "input file path: " << input_path << std::endl; + std::cout << "output file path: " << output_path << std::endl; + std::cout << "width: " << width << std::endl; + std::cout << "height: " << height << std::endl; + std::cout << "bit depth: " << bit_depth << std::endl; + std::cout << std::endl; + } + + + /** + * Saves class image data to output file. + */ + void save() { + std::cout << "Attempting to save image to \"" << output_path << "\"." << std::endl; + + // Open output file stream. + std::ofstream output_file; + + // Attempt to save file data. + try { + // Attempt to open file. + output_file.open(output_path, std::ios::binary | std::ios::out); + + // Check if opened successfully. + if (output_file.fail()) { + // Failed to open. + std::cout << "Failed to open file \"" + output_path + "\".\n"; + } else { + // Opened successfully. + + // Write image "header" data. + output_file << "P6\n" << width << " " << height << "\n255\n"; + + // Write image pixel data. + unsigned char r, g, b; + for (int index = 0; index < (width * height); index++) { + r = static_cast<float>(std::min(1.f, pixel_arr[index].r) * 255); + g = static_cast<float>(std::min(1.f, pixel_arr[index].g) * 255); + b = static_cast<float>(std::min(1.f, pixel_arr[index].b) * 255); + output_file << r << g << b; + } + + } + + // Close file stream. + output_file.close(); + std::cout << "Image saved." << std::endl; + + } catch (const char* err) { + fprintf(stderr, "%s\n", err); + output_file.close(); + } } + //endregion Public Methods. + }; +// Preset single colors. Mostly for testing purposes. +const Image::Rgb Image::pixelBlack = Image::Rgb(0); +const Image::Rgb Image::pixelWhite = Image::Rgb(1); +const Image::Rgb Image::pixelRed = Image::Rgb(1,0,0); +const Image::Rgb Image::pixelGreen = Image::Rgb(0,1,0); +const Image::Rgb Image::pixelBlue = Image::Rgb(0,0,1); +const Image::Rgb Image::pixelYellow = Image::Rgb(1,1,0); +const Image::Rgb Image::pixelPink = Image::Rgb(1,0,1); +const Image::Rgb Image::pixelLiBlue = Image::Rgb(0,1,1); + + /* * Program's main. Initializes and runs program. */ int main(int argc, char* argv[]) { printf("Starting program.\n"); printf("\n"); + printf("\n"); - Image image; - image.test_method(); - - // // Check provided number of args. - // if (argc < 2) { - // // No args provided. - // printf("Provided too few program args. Expected one arg."); - // } else if (argc > 2) { - // // More than one arg provided. - // printf("Provided too many program args. Expected one arg."); - // } else { - // // Correct number of args provided. Attempt to process. - - // // Check data type. - // std::string path_str = argv[1]; - // path_validator_struct* return_struct = validate_path(path_str); - // int path_type = return_struct->file_type; - // if (return_struct->err_code) { - // std::cerr << "Error in is_regular_file: " << return_struct->err_code.message(); - // } - // free_path_validator_struct(return_struct); - - // // Handle based on provided type. - // if (path_type == TYPE_DIR) { - // // Process dir. - // process_dir(path_str); - // } else if (path_type == TYPE_FILE) { - // // Process file. - // process_file(path_str); - // } - // } + // Check provided number of args. + if (argc < 2) { + // No args provided. + printf("Provided too few program args. Expected one arg."); + } else if (argc > 2) { + // More than one arg provided. + printf("Provided too many program args. Expected one arg."); + } else { + // Correct number of args provided. Pass to image class for processing. + + // Check data type. + std::string path_str = argv[1]; + path_validator_struct* return_struct = validate_path(path_str); + int path_type = return_struct->file_type; + if (return_struct->err_code) { + std::cerr << "Error verifying file type: " << return_struct->err_code.message() << std::endl; + } + free_path_validator_struct(return_struct); + + // Handle based on provided type. + if (path_type == TYPE_DIR) { + // Process dir. + process_dir(path_str); + } else if (path_type == TYPE_FILE) { + // Process file. + process_file(path_str); + } + } - // printf("\n"); - // printf("Terminating program.\n"); - // exit(0); + printf("\n"); + printf("\n"); + printf("Terminating program.\n"); + exit(0); } - /** * Validates provided path and if valid, determines path type. * Returns struct of data. @@ -154,63 +291,63 @@ void process_dir(std::string path_str) { */ void process_file(std::string path_str) { - // Open input file. - std::ifstream input_file; - input_file.open(path_str, std::ios::binary | std::ios::in); - if (! input_file.good()) { - std::cout << "Failed to open file \"" + path_str + "\".\n"; - } - - // Calculate output path location. - std::string base_filename = path_str.substr(path_str.find_last_of("/\\") + 1); - std::string output_path_str = "../output/" + base_filename; + Image image; + image.display_properties(); + image.save(); + + // // Open input file. + // std::ifstream input_file; + // input_file.open(path_str, std::ios::binary | std::ios::in); + // if (! input_file.good()) { + // std::cout << "Failed to open file \"" + path_str + "\".\n"; + // } - // Open output file. - std::ofstream output_file; - output_file.open(output_path_str, std::ios::binary | std::ios::out); - if (! output_file.good()) { - std::cout << "Failed to open file \"" + output_path_str + "\".\n"; - } + // // Calculate output path location. + // std::string base_filename = path_str.substr(path_str.find_last_of("/\\") + 1); + // std::string output_path_str = "../output/" + base_filename; - // Copy file over. - if (input_file.good() && output_file.good()) { - // output_file << input_file; - - // int buffer[100]; - // while (input_file.read( (char*) &buffer, sizeof(buffer)) ) { - // output_file.write( (char*) &buffer, sizeof(buffer) ); - // } - - // std::copy( - // std::istreambuf_iterator<char>(input_file), - // std::istreambuf_iterator<char>( ), - // std::ostreambuf_iterator<char>(output_file) - // ); - - std::string header; - int w, h, b; - input_file >> header; - if (strcmp(header.c_str(), "P6") != 0) { - throw("Can't read input file"); - } else { - printf("header: %s\n\n", header.c_str()); - } + // // Open output file. + // std::ofstream output_file; + // output_file.open(output_path_str, std::ios::binary | std::ios::out); + // if (! output_file.good()) { + // std::cout << "Failed to open file \"" + output_path_str + "\".\n"; + // } - input_file >> w >> h >> b; - printf("w: %i\n\n", w); - printf("h: %i\n\n", h); - printf("b: %i\n\n", b); + // // Copy file over. + // if (input_file.good() && output_file.good()) { + // // output_file << input_file; + + // // int buffer[100]; + // // while (input_file.read( (char*) &buffer, sizeof(buffer)) ) { + // // output_file.write( (char*) &buffer, sizeof(buffer) ); + // // } + + // // std::copy( + // // std::istreambuf_iterator<char>(input_file), + // // std::istreambuf_iterator<char>( ), + // // std::ostreambuf_iterator<char>(output_file) + // // ); + + // std::string header; + // input_file >> header; + // if (strcmp(header.c_str(), "P6") != 0) { + // throw("Can't read input file"); + // } else { + // printf("header: %s\n\n", header.c_str()); + // } + // input_file >> width >> height >> bit_depth; + // printf("width: %i\n", width); + // printf("height: %i\n", height); + // printf("bit depth: %i\n", bit_depth); - input_file.close(); - output_file.close(); - } + // input_file.close(); + // output_file.close(); + // } } - - // /* // * Program's main. Initializes and runs program. // */