delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/18/08:30:19

From: mc8860 AT pop DOT ou DOT edu (Jason McCullough)
Newsgroups: comp.os.msdos.djgpp
Subject: DJGPP behaves differently from GCC. Possible Bug? Help needed.......
Date: Thu, 17 Apr 1997 16:55:06 GMT
Organization: Maximum Caffination.
Lines: 476
Message-ID: <33565468.13125228@ounews.ou.edu>
NNTP-Posting-Host: cate0-120.reshall.ou.edu
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Thankfully, I turned this project in already.  But a part of the
program that isn't graded still doesn't work.  I'm reading a P5 pgm
image file in, and performing an edge detection operation on it, then
dumping it out in P2 pgm format.  When I compile it on the University
alphas here at school, it works just fine.  Compile it with DJGPP,
exact same source code, and the edge detection outputs nothing but
black pixels after 20k or so.  Rather cryptic.  Both DJGPP -v on my
dos box and g++ -v on the alphas here give version 2.7.2.1.
I added a line after the pixel read to dump that pixel to a diagnostic
file, and checked; the pixels are screwed up when they're originally
read.

Can someone *plueeeze* point out what the incompatibility is here,
since you *really really* want to waste your time on this?

Welp, here's the code.  Email me at mc8860 AT pop DOT ou DOT edu if there's any
actual followups to this.


// start file
// image class declarations

#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>
#include <math.h>

// This class reads, writes, and performs edge an detection operation
on
// PGM files of either P2 or P5 format.

class image {
private:
	int rows, cols, type, maxgrey;
	int **data;                    // 2 dimensional array to store
PGM
				       // pixel values; to be
dynamically
				       // allocated
public:
	image();                                    // default
constructor
	image(int num_rows, int num_cols, int max_grey,  int
**&values);
	                                           // construct image
when
						   // passed all
values
	image(image &initimage);                   // copy constructor
	~image();
	image edges(int thresholdvalue);
        image& operator=(const image &initial);
	                     // overloaded operators for reading and
writing
			     // the images
	friend ostream& operator<<(ostream&, image&); 
	friend istream& operator>>(istream&, image&);
	};

// image class definition

//
---------------------------------------------------------------------
// Description:  This is the default constructor for the image class.
// Preconditions: None.
// Postconditions:  The image is created with default values.
// Return Value:  None.

image::image()
{
        type = 0;
        rows = 0;
        cols = 0;
	maxgrey = 0;
	data = NULL;
}

//
---------------------------------------------------------------------
// Description:  This is the constructor for which all values are
passed in.
// Preconditions: Int r is the number of rows of pixels, int c the
number of
// columns, int g the maximum grey value of a pixel, and int **& is a
// 2 dimensional array of the pixel values in row major order.
// Postconditions:  The image is created with the passed in values.
// Return Value:  None.

image::image(int r, int c, int g, int **& values)
{
        type = 0;
	rows = r;
	cols = c;
	maxgrey = g;

// Allocate storage

        data = new (int *)[rows];

	for (int i=0; i < rows; i++)
	{
		data[i]=new (int)[cols];
	}

// read in values

	for (int j=0; j < rows; j++)
	{
		for (int k=0; k < cols; k++)
		{
		  data[j][k] = values[j][k];
		}
	}
        
}

image::image(image &initimg)
{
      rows = initimg.rows;
      cols = initimg.cols;
      type = initimg.type;
      maxgrey = initimg.maxgrey;

// Allocate storage

        data = new (int *)[rows];

	for (int i=0; i < rows; i++)
	{
		data[i]=new (int)[cols];
	}

// read in values

	for (int j=0; j < rows; j++)
	{
		for (int k=0; k < cols; k++)
		{
		  data[j][k] = initimg.data[j][k];
		}
	}
}

//
---------------------------------------------------------------------
// Description:  This is the equals operator for the image class.
// Preconditions: A constant reference to the image to be copied.
// Postconditions:  The image owning the operation now contains the
values
// of the constant reference image.
// Return Value:  A reference to the modified image

image& image::operator=(const image& initimg)
{
  if (this != &initimg)       // check for initimg = initimg or
equivalent
    {
      for (int z=0; z < rows; z++)    // wipe data, making sure to get
	delete[] data[z];             // all of the 2d array
      delete[] data;
      rows = initimg.rows;
      cols = initimg.cols;
      type = initimg.type;
      maxgrey = initimg.maxgrey;

// Allocate storage

        data = new (int *)[rows];

	for (int i=0; i < rows; i++)
	{
		data[i]=new (int)[cols];
	}

// read in values

	for (int j=0; j < rows; j++)
	{
		for (int k=0; k < cols; k++)
		{
		  data[j][k] = initimg.data[j][k];
		}
	}
    }
        return(*this);
}     

//
---------------------------------------------------------------------
// Description:  This is the destructor for the image class.
// Preconditions: A created image, which is the owner of the
operation.
// Postconditions:  The owner image has had its allocated space for
data[][]
// deallocated.
// Return Value:  None.

image::~image()
{
        for (int i=0; i < rows; i++)           // wipe data, making
sure
	  delete[] data[i];                    // to get all of the 2d
array
	delete[] data;
}

//
---------------------------------------------------------------------
// Description:  This is the overloaded >> (read) operator for the
image class.
// Preconditions: A input stream ins, and a reference to a created
image.
// Postconditions:  The owning image now contains the row, column,
maximum grey
// value, type, and pixel data from the input stream.
// Return Value:  A reference to the input stream.

istream& operator>>(istream& ins, image& current)
{
  int linel = 79;               // maximum length of a line
  unsigned char temp;           // temporary variable for reading one
P5 pixel
  char buffer[linel];

	if (!ins)
	  { cerr << "Input file does not exist, or is not"
	      << "accessible.\n";
	    exit (2);
	  }

	ins.get(temp);		  	        // skip to 5 or 2
	ins.getline(buffer, linel);
	current.type = atoi(buffer);
	ins.getline(buffer, linel, ' ');	// change seperator to
space
						// so only one word is
read
	current.rows = atoi(buffer);
	ins.getline(buffer, linel);
	current.cols = atoi(buffer);
	ins.getline(buffer, linel);
	current.maxgrey = atoi(buffer);

	// allocate space
        current.data = new (int *)[current.rows];

	for (int i=0; i < current.rows; i++)
	{
		current.data[i]=new (int)[current.cols];
	}

	// check for p2 or p5 image, and read in pixel data
        if (current.type == 2)
	  {
	    for (int j=0; j < current.rows; j++)
	      {
		for (int k=0; k < current.cols; k++)
		{
			ins >> current.data[j][k];
		}
	      }
	  }

	else {
	  for (int j=0; j < current.rows; j++)
	      {
		for (int k=0; k < current.cols; k++)
		{
			ins.get(temp);
			current.data[j][k] = temp;
		}
	      }
	}
	return ins;
}

//
---------------------------------------------------------------------
// Description: This is the overloaded output(<<) operator for the
image class.
// Preconditions: An ostream, and a reference to the
// image owning the operation.
// Postconditions:  The values of the image are written to the ostream
in
// P2 format
// Return Value:  A reference to the ostream.

ostream& operator<<(ostream& outs, image& current)
{
                          // output format, rows, cols, and maximum
grey value
        outs << "P2\n";
	outs << (current.rows) << " " << (current.cols) << "\n";
	outs << (current.maxgrey) << "\n";

	                  // output pixels
	for (int i=0; i < (current.rows); i++)
	{
		for (int j=0; j < (current.cols); j++)
		{
			outs << current.data[i][j];
			if (j != (current.cols - 1))
				outs << " ";
		}
		outs << "\n";
	}
	return outs;
}

//
---------------------------------------------------------------------
// Description: This is the edge detection/calculation operation for
// the image class.
// Preconditions: The image owning the operation and an integer
threshold
// to compare the edge values with.
// Postconditions:  None.
// Return Value:  A copy of the newly created image file with the
edges
// detected and shown.

image image::edges(int threshold)
{
	int xedge, yedge;
	int **deriv;

	             // allocate space for edge detection results
        deriv = new (int *)[rows - 2];

	for (int i=0; i < (rows - 2); i++)
	{
		deriv[i]=new (int)[cols - 2];
	}

// Calculate derivative values for array, store in temparray array
// Derivative algorithm:  a b c
//	  	          d e f
//		          g h i
//				horiz_edge =  a + b + c - g - h - i
//				vertic_edge = a + d + g - c - f - i
// edge = sqrt(sqr(horiz_edge) + sqr(vertic_edge))
			
		    // calculate from 1 to rows - 1 and cols - 1
(operation
		    // is undefined for edge pixels)
	for (int j=1; j < (rows - 1); j++)
	{
		for (int k=1; k < (cols - 1); k++)
		{
		xedge = data[j-1][k-1] + data[j-1][k] +
			data[j-1][k+1] - data[j+1][k-1]
			- data[j+1][k] - data[j+1][k+1];

		yedge = data[j-1][k-1] + data[j][k-1] +
			data[j+1][k-1] - data[j-1][k+1]
			- data[j][k+1] - data[j+1][k+1];

		deriv[j-1][k-1] = (int)sqrt((xedge * xedge) + (yedge *
yedge));
		}
	}

// Compare derivatives to the threshold; if the derivative is
// equal to or larger than the threshold, replace value with maxgrey;
// else replace pixel value with 0

	for (int m=0; m < (rows - 2); m++)
	{
	for (int n=0; n < (cols - 2); n++)
		{
		  if ((deriv[m][n]) >= threshold)
		      deriv[m][n] = maxgrey;
		  else deriv[m][n] = 0;
		}
	}
               // create new image with edges detected (deriv[][]
values)
        image new_image(rows - 2, cols - 2, maxgrey, deriv);
	return(new_image);
}


// Description: This program performs a basic edge detection on either
a
// P2 or P5 format Portable Grey Map image file.
//
// Input: The names of the input & output image files, along with the
// threshold value, are taken as command line arguments.  For both
// formats, the first line of the pgm file consists of the letters P2
or
// P5 followed by a carriage return.  The second line is the row and
// column size followed by a carriage return.  The third line consists
// of the maximum grey value defined followed by a carriage return.
// Then, for a P2 file, the grey values of all the pixels in the image
are
// stored thereafter in ascii format, (1, 5, 255, etc), one row to a
line.
// For a P5 image, the rest of the file consists of the grey value of
all
// the pixels listed in top-down left to right format, stored in
binary.
// The values of the pixels may vary from 255(white) to 0(black) for
this
// project.
//
// Error Checking: If filenames for the image files and the threshold
are
// not provided as command line arguments, the program exits and
returns a
// value of 1.  If the input file does not exist, the program also
exits
// with a return value of 2.
//
// Output: A P2 format PGM image file with the edges detected and
displayed.
//
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

//************************************************************************
//				Main Program
//************************************************************************

//
----------------------------------------------------------------------
// Description:  The main program calls member functions of the pgm
file to
// read the file into the class, calculate the edges, 
// and then write the new image with edges back to disk.
// Error checking of the number of command line parameters and valid
open
// of the input file is done.
//
// Input: The number of arguments on the calling command line, and a
pointer
// to an array of strings holding those arguments.
// Output:  None
// Return value: 0 if successful; 1 if not enough command line
arguments;
// and 2 if the input file could not be opened.

//************************************************************************

int
main(int argcnt, char *args[])
{
        int threshold;
	image pgmfile, newfile;

// Check for command line errors
	if (argcnt != 4)
	{ cerr << "Please input the correct input, output and
threshold "
	       << "filenames again.\n";
	  exit (1);
	}

// Assign threshold to integer variable from command line string
	threshold = atoi(args[3]);

// Read input file into class
	ifstream ins(args[1], ios::in);
	ins >> pgmfile;
	ins.close();

// Calculate edges for the pgm, store the value in a new pgm
        newfile = pgmfile.edges(threshold);

// Write new image
	ofstream outs(args[2], ios::out);
	outs << newfile;
	outs.close();
	
	return(0);
}
//	End of main program

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019