From b75f9120daef13c4daeac6c9aefb32cee4517317 Mon Sep 17 00:00:00 2001 From: Stefan Suhren Date: Thu, 8 May 2014 12:08:39 +0200 Subject: Assignment No. 1 This program manipulates pgm images. --- 1.01.bildverarbeitung3.cc | 366 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 1.01.bildverarbeitung3.cc (limited to '1.01.bildverarbeitung3.cc') diff --git a/1.01.bildverarbeitung3.cc b/1.01.bildverarbeitung3.cc new file mode 100644 index 0000000..08c3a1c --- /dev/null +++ b/1.01.bildverarbeitung3.cc @@ -0,0 +1,366 @@ +/* + * ===================================================================================== + * + * Filename: 1.01.bildverarbeitung3.cc + * + * Description: + * + * Version: 1.0 + * Created: 20.03.2014 12:24:17 + * Revision: none + * Compiler: gcc + * + * Author: Stefan Suhren (SSuhren), suhren.stefan@fh-swf.de + * Organization: FH Südwestfalen, Iserlohn + * + * ===================================================================================== + */ + +#include +#include +#include +#include +#include + +using namespace std; + +//----------------------------------------------------------------------------- +// Type Defs +//----------------------------------------------------------------------------- + +typedef unsigned char Pixel; + +// ##### DATA TYPES - LOCAL TO THIS SOURCE FILE ############################## +struct pgm_bild +{ + char magic[2]; // Bildtyp + int nx; // Zeilenzahl + int ny; // Spaltenzahl + int graumax; // max. Grauwert + Pixel **bild; // Bildmatrix +}; // ---------- end of struct pgm_bild ---------- + +// ##### LOCAL PROTOTYPES ###################################################### +void bild_lesen( pgm_bild *bild, char *ifs_file_name ); +void bild_schreiben( pgm_bild *bild, char *ofs_file_name ); +void delete_pixel_matrix( Pixel **m ); +Pixel** new_pixel_matrix( size_t rows, size_t columns ); +void glaetten( pgm_bild *bild1, pgm_bild *bild2 ); +void invertieren( pgm_bild *bild1, pgm_bild *bild2 ); +void kantenbildung( pgm_bild *bild1, pgm_bild *bild2 ); +void kopiere_bildkopf( pgm_bild *bild1, pgm_bild *bild2 ); +void schwellwert( pgm_bild *bild1, pgm_bild *bild2, Pixel schwellwert ); + +// === FUNCTION ====================================================================== +// Name: main +// Description: Main loop for user interactions +// Exitcodes: 0 success +// 1 file open failure +// 2 type missmatch +// 3 header corrupted +// 4 image to narrow +// 5 image to low +// 6 pixel read error +// 7 pixel outside of interval +// ===================================================================================== +int main( int argc, char *argv[] ){ + + pgm_bild pic1; + pgm_bild pic2; + + char menu = 'e'; // user input for conversion + + char ifs_file_name[] = "dreifach.pgm"; // input file name + char ofs_file_name[] = "dreifach.out.pgm"; // output file name + + bild_lesen(&pic1, ifs_file_name); + pic2.bild = new_pixel_matrix(1,1); + + do{ // repeates till user presses e + cout << "c Kopieren\ng Glätten\ni Invertieren\nk Kantenbildung\ns Schwellwert\ne ENDE\n?"; + cin >> menu; + if(menu != 'e'){ + + switch (menu){ // change output + case 'g': + glaetten(&pic1, &pic2); + break; + case 'i': + invertieren(&pic1, &pic2); + break; + case 'k': + kantenbildung(&pic1, &pic2); + break; + case 's': + schwellwert(&pic1, &pic2, 150); + break; + case 'c': + kopiere_bildkopf(&pic1, &pic2); + for(int i = 0; i < pic2.nx; i++){ // height + for(int j = 0; j < pic2.ny; j++){ // width + pic2.bild[i][j] = pic1.bild[i][j]; + } + } + break; + } + + bild_schreiben(&pic2, ofs_file_name); + } + + }while(menu != 'e'); + + return EXIT_SUCCESS; +} // ---------- end of function main ---------- + +// === FUNCTION ====================================================================== +// Name: bild_lesen +// Description: Reads image from the file ifs_file_name +// ===================================================================================== +void bild_lesen( pgm_bild *bild, char *ifs_file_name ){ + + int temp = 0; // reads the vales from input file + + string cod; // coding string at the beginning + + // Open file for manipulation + ifstream ifs; // create ifstream object + + ifs.open ( ifs_file_name ); // open ifstream + if (!ifs) { + cerr << "\nERROR : failed to open input file " << ifs_file_name << endl; + exit (EXIT_FAILURE); + } + + getline(ifs, cod); // reads hole line + + if( cod != "P2"){ // type must match + ifs.close(); // release file handler + cerr << "File type wrong."; + exit(2); + } + else{ + bild->magic[0] = cod[0]; + bild->magic[1] = cod[1]; + } + + if(!(ifs >> bild->ny)){ // Header corrupted (width) + ifs.close(); + cerr << "Header corrupted."; + exit(3); + } + + if(!(ifs >> bild->nx)){ // Header corrupted (height) + ifs.close(); + cerr << "Header corrupted."; + exit(3); + } + + if(!(ifs >> bild->graumax)){ // Header corrupted + ifs.close(); + cerr << "Header corrupted."; + exit(3); + } + + if( bild->ny <= 0 ){ // image to narrow + ifs.close(); // release file handler + cerr << "Image is to narrow."; + exit(4); + } + + if( bild->nx <= 0 ){ // image to low + ifs.close(); // release file handler + cerr << "Image is to low."; + exit(5); + } + + // Create a new pixel matrix for the image + bild->bild = new_pixel_matrix(bild->nx, bild->ny); + + cout << "File type: " << bild->magic << endl // printing for debug perposes + << "Width: " << bild->ny << endl + << "Height: " << bild->nx << endl + << "maxGrey: " << bild->graumax << endl; + + for(int i = 0; i < bild->nx; i++){ // Height + for(int j = 0; j < bild->ny; j++){ // Width + if(ifs >> temp){ // to prevent char by char reading + if(temp >= 0 && temp <= bild->graumax){ + bild->bild[i][j] = temp; // reading input file + } + else{ + cerr << "Pixel out of interval"; + ifs.close(); + exit(7); + } + } + else{ + cerr << "Pixel read error" << endl; + ifs.close(); + exit(6); + } + } + } + + ifs.close (); // close ifstream +} + +// === FUNCTION ====================================================================== +// Name: bild_schreiben +// Description: Writes image to file ofs_file_name +// ===================================================================================== +void bild_schreiben( pgm_bild *bild, char *ofs_file_name ){ + + ofstream ofs; // create ofstream object + + ofs.open ( ofs_file_name ); // open ofstream + if (!ofs) { + cerr << "\nERROR : failed to open output file " << ofs_file_name << endl; + exit (EXIT_FAILURE); + } + + ofs << bild->magic << endl // writing header + << bild->ny << " " << bild->nx << endl + << bild->graumax << endl; + + for(int i = 0; i < bild->nx; i++){ + for(int j = 0; j < bild->ny; j++){ + ofs << (int) bild->bild[i][j] << ' '; // and writing changed image (don't forget the ' ') + } + ofs << endl; + } + + ofs.close (); // close ofstream +} + +void delete_pixel_matrix( Pixel **m ){ + delete[] *m; // delete data pointer + delete[] m; // delete pointer array +} + + +// === FUNCTION ====================================================================== +// Name: new_pixel_matrix +// Description: Creates a new pixel matrix with a few tricks +// ===================================================================================== +Pixel** new_pixel_matrix( size_t rows, size_t columns ){ + size_t i; + Pixel **m; + m = new Pixel* [rows]; // allocate pointer array + *m = new Pixel [rows*columns]; // allocate data array + for( i = 1; iny; i++){ // width + bild2->bild[0][i] = bild1->bild[0][i]; // copy first row + } + for(int i = 1; i < bild2->nx-1; i++){ // height + bild2->bild[i][0] = bild1->bild[i][0]; // copy first pixel every row + for(int j = 1; j < bild2->ny-1; j++){ // width + bild2->bild[i][j] = ( bild1->bild[i-1][j-1] + + bild1->bild[i-1][j] + + bild1->bild[i-1][j+1] + + bild1->bild[i][j-1] + + bild1->bild[i][j] + + bild1->bild[i][j+1] + + bild1->bild[i+1][j-1] + + bild1->bild[i+1][j] + + bild1->bild[i+1][j+1]) / 9; + } + bild2->bild[i][bild2->ny-1] = bild1->bild[i][bild2->ny-1]; // copy last pixel every row + } + for(int i = 0; i < bild2->ny; i++){ // width + bild2->bild[bild2->nx-1][i] = bild1->bild[bild2->nx-1][i]; // copy last row + } +} + +// === FUNCTION ====================================================================== +// Name: invertieren +// Description: bild2 is a inverted version of bild1 +// ===================================================================================== +void invertieren( pgm_bild *bild1, pgm_bild *bild2 ){ + // Copy the neccessary values + kopiere_bildkopf( bild1, bild2 ); + + for(int i = 0; i < bild2->nx; i++){ // height + for(int j = 0; j < bild2->ny; j++){ // width + bild2->bild[i][j] = bild2->graumax - bild1->bild[i][j]; // inverts value by subtracting from graumax + } + } +} + +// === FUNCTION ====================================================================== +// Name: kantenbildung +// Description: bild2 is a edged version of bild1 +// ===================================================================================== +void kantenbildung( pgm_bild *bild1, pgm_bild *bild2 ){ + // Copy the neccessary values + kopiere_bildkopf( bild1, bild2); + + for(int i = 0; i < bild2->ny; i++){ // width + bild2->bild[0][i] = 0; // blacken the first row + } + for(int i = 1; i < bild2->nx-1; i++){ // height + bild2->bild[i][0] = 0; // blacken the first pixel every row + for(int j = 1; j < bild2->ny-1; j++){ // width + bild2->bild[i][j] = abs(( -1*bild1->bild[i-1][j] + -1*bild1->bild[i][j-1] + +4*bild1->bild[i][j] + -1*bild1->bild[i][j+1] + -1*bild1->bild[i+1][j] ) /9 ); + } + bild2->bild[i][bild2->ny-1] = 0; // blacken the last pixel every row + } + for(int i = 0; i < bild2->ny; i++){ // width + bild2->bild[bild2->nx-1][i] = 0; // blacken the last row + } +} + +// === FUNCTION ====================================================================== +// Name: kopiere_bildkopf +// Description: Copies the Header and allocates a new matrix (frees old) +// ===================================================================================== +void kopiere_bildkopf( pgm_bild *bild1, pgm_bild *bild2 ){ + // Copy the magic value + for(unsigned int i = 0; i < (sizeof bild1->magic/sizeof bild1->magic[0]); i++){ + bild2->magic[i] = bild1->magic[i]; + } + + // Copy over the height/width + bild2->nx = bild1->nx; + bild2->ny = bild1->ny; + + // Copy graumax + bild2->graumax = bild1->graumax; + + //Free memory + delete_pixel_matrix(bild2->bild); + bild2->bild = new_pixel_matrix( bild2->nx, bild2->ny); +} + +// === FUNCTION ====================================================================== +// Name: schwellwert +// Description: bild2 is a polarised version of bild1 parted by schwellwert +// ===================================================================================== +void schwellwert( pgm_bild *bild1, pgm_bild *bild2, Pixel schwellwert){ + for(int i = 0; i < bild2->nx; i++){ // height + for(int j = 0; j < bild2->ny; j++){ // width + if( bild1->bild[i][j] < schwellwert ){ // value < schwellwert, image black + bild2->bild[i][j] = 0; + } + else{ // else white + bild2->bild[i][j] = bild2->graumax; + } + } + } +} -- cgit v1.2.3-70-g09d2