Esempio n. 1
0
void getRotationMatrixFromOrientation(double out[9], double orientation[3])
{
	double xM[9];
	double yM[9];
	double zM[9];

	double sinX = sin(orientation[1]);
	double cosX = cos(orientation[1]);
	double sinY = sin(orientation[2]);
	double cosY = cos(orientation[2]);
	double sinZ = sin(orientation[0]);
	double cosZ = cos(orientation[0]);

	// rotation about x-axis (pitch)
	xM[0] = 1.0f; xM[1] = 0.0f; xM[2] = 0.0f;
	xM[3] = 0.0f; xM[4] = cosX; xM[5] = sinX;
	xM[6] = 0.0f; xM[7] = -sinX; xM[8] = cosX;

	// rotation about y-axis (roll)
	yM[0] = cosY; yM[1] = 0.0f; yM[2] = sinY;
	yM[3] = 0.0f; yM[4] = 1.0f; yM[5] = 0.0f;
	yM[6] = -sinY; yM[7] = 0.0f; yM[8] = cosY;

	// rotation about z-axis (azimuth)
	zM[0] = cosZ; zM[1] = sinZ; zM[2] = 0.0f;
	zM[3] = -sinZ; zM[4] = cosZ; zM[5] = 0.0f;
	zM[6] = 0.0f; zM[7] = 0.0f; zM[8] = 1.0f;

	// rotation order is y, x, z (roll, pitch, azimuth)
	matrixMultiplication(out, xM, yM);
	matrixMultiplication(out, zM, out);
}
Esempio n. 2
0
	/** From http://www.thousand-thoughts.com/2012/03/android-sensor-fusion-tutorial/2/
	 *  Should be optimized ... */
	void getRotationMatrixFromOrientation(float* orientation, float* result)
	{
		float xM[9];
		float yM[9];
		float zM[9];

		float sinX = (float)qSin(orientation[1]);
		float cosX = (float)qCos(orientation[1]);
		float sinY = (float)qSin(orientation[2]);
		float cosY = (float)qCos(orientation[2]);
		float sinZ = (float)qSin(orientation[0]);
		float cosZ = (float)qCos(orientation[0]);

		// rotation about x-axis (pitch)
		xM[0] = 1.0f; xM[1] = 0.0f; xM[2] = 0.0f;
		xM[3] = 0.0f; xM[4] = cosX; xM[5] = sinX;
		xM[6] = 0.0f; xM[7] = -sinX; xM[8] = cosX;

		// rotation about y-axis (roll)
		yM[0] = cosY; yM[1] = 0.0f; yM[2] = sinY;
		yM[3] = 0.0f; yM[4] = 1.0f; yM[5] = 0.0f;
		yM[6] = -sinY; yM[7] = 0.0f; yM[8] = cosY;

		// rotation about z-axis (azimuth)
		zM[0] = cosZ; zM[1] = sinZ; zM[2] = 0.0f;
		zM[3] = -sinZ; zM[4] = cosZ; zM[5] = 0.0f;
		zM[6] = 0.0f; zM[7] = 0.0f; zM[8] = 1.0f;

		// rotation order is y, x, z (roll, pitch, azimuth)
		float temp[9];
		matrixMultiplication(xM, yM, temp);
		matrixMultiplication(zM, temp, result);
	}
Esempio n. 3
0
/// Computes lighting for the entire scene
void computeLighting()
{
    for (auto &ridge : mountains)
    {
        for (int i=0; i < ridge.meshVertices.size(); i = i+3)
        {
            // Compute for our (single) light
            Vec3Df vertexpos = Vec3Df(ridge.meshVertices[i],
                                      ridge.meshVertices[i+1],
                                      ridge.meshVertices[i+2]);
            Vec3Df normal = Vec3Df(ridge.meshNormals[i],
                                   ridge.meshNormals[i+1],
                                   ridge.meshNormals[i+2]);
            Vec3Df lighting = computeLighting(vertexpos, normal, DIFFUSE_LIGHTING);
            
            // Pass computed values to Ridge
            ridge.meshColors[i] = lighting[0];
            ridge.meshColors[i+1] = lighting[1];
            ridge.meshColors[i+2] = lighting[2];
        }
    }
	
	if (toggleBoss) {
		std::vector<Vertex> vertices = boss.getMesh().vertices;
		std::vector<Vec3Df> meshColors = std::vector<Vec3Df>(vertices.size());

		auto rotMat = matrixMultiplication(
			rotateMatrixY(boss.angleHeadY*M_PI / 180),
			rotateMatrixX(boss.angleHeadZ*M_PI / 180)
			);

		for (int i = 0; i < vertices.size(); i++)
		{
			// Compute for our (single) light
			Vertex vertex = vertices[i];
			Vec3Df vec = vertex.p;
			vec = calculateMatrix(rotMat, vec);
			vec = vec + boss.translation;
			vec = vec * boss.scale;
			vec = vec + boss.position;

			Vec3Df nor = vertex.n;
			nor = calculateMatrix(rotMat, nor);
			nor = nor + boss.translation;
			nor = nor * boss.scale;
			nor = nor + boss.position;

			Vec3Df lighting = computeLighting(vec, nor, PHONG_LIGHTNING);

			meshColors[i] = lighting;
		}
		boss.getMesh().meshColor = meshColors;
	}
}
Esempio n. 4
0
// This function performs the integration of the gyroscope data.
// It writes the gyroscope based orientation into gyroOrientation.
void gyroFunction(void)
{
	//static double NS2S = 1.0f / 1000000000.0f;
	//double timestamp;

	// don't start until first accelerometer/magnetometer orientation has been acquired
	//if (accMagOrientation == null)
	//return;

	// initialisation of the gyroscope based rotation matrix
	static bool initState = true;
	if (initState) {
		double initMatrix[9];
		getRotationMatrixFromOrientation(initMatrix, accMagOrientation);
		double test[3];
		getOrientation(test, initMatrix);
		matrixMultiplication(gyroMatrix, gyroMatrix, initMatrix);
		initState = false;
	}

	// copy the new gyro values into the gyro array
	// convert the raw gyro data into a rotation vector
	double deltaVector[4];
		//const double dT = (timer_systime() - timestamp) * NS2S;
		//System.arraycopy(event.values, 0, gyro, 0, 3);
		getRotationVectorFromGyro(deltaVector, G_Dt);

	// measurement done, save current time for next interval
	//timestamp = timer_systime();

	// convert rotation vector into rotation matrix
	double deltaMatrix[9];
	getRotationMatrixFromVector(deltaMatrix, deltaVector);

	// apply the new rotation interval on the gyroscope based rotation matrix
	matrixMultiplication(gyroMatrix, gyroMatrix, deltaMatrix);

	// get the gyroscope based orientation from the rotation matrix
	getOrientation(gyroMatrix, gyroOrientation);
}
void compute()
{
    int i, j;
    float angle;
    float **pt, **tmp;
    
    /* pt is 1 by 3 */
    pt = (float**)mxCalloc(1,sizeof(*pt));
    for( i = 0; i < 1; ++i )
    {
        pt[i] = (float*)mxCalloc(3,sizeof(**pt));
    }
    /* tmp is 1 by 3 */
    tmp = (float**)mxCalloc(1,sizeof(*tmp));
    for( i = 0; i < 1; ++i )
    {
        tmp[i] = (float*)mxCalloc(3,sizeof(**tmp));
    }
    
    /* set the transformation matrix */
    A1 = (float**)mxCalloc(3,sizeof(*A1));
    for( i = 0; i < 3; ++i )
    {
        A1[i] = (float*)mxCalloc(3,sizeof(**A1));
    }
    A2 = (float**)mxCalloc(3,sizeof(*A2));
    for( i = 0; i < 3; ++i )
    {
        A2[i] = (float*)mxCalloc(3,sizeof(**A2));
    }
    for( i = 0; i < 3; ++i )
        for( j = 0; j < 3; ++j )
        {
            A1[i][j] = 0;
            A2[i][j] = 0;
        }
    A1[0][0] = cScale * pow( (double)2, (double)(tScale/2) );
    A1[1][1] = rScale * pow( (double)2, (double)(tScale/2) );

    angle = rotation * PI/nOri;
    
    A2[0][0] = cos(angle); 
    A2[0][1] = sin(angle);
    A2[1][0] = -A2[0][1];
    A2[1][1] = A2[0][0];
        
    for( i = 0; i < nElement; ++i )
    {
        tmp[0][0] = inCol[i];
        tmp[0][1] = -inRow[i];
        tmp[0][2] = 1;
        matrixMultiplication(1,3,tmp,3,A1,pt);
        tmp[0][0] = pt[0][0];
        tmp[0][1] = pt[0][1];
        tmp[0][2] = pt[0][2];
        matrixMultiplication(1,3,tmp,3,A2,pt);
        
        outCol[i] = ROUND( pt[0][0] );
        outRow[i] = ROUND( -pt[0][1] );
        outO[i] = inO[i] + rotation;
        outS[i] = inS[i] + tScale;
        
        /*
        while( outO[i] < 0 )
            outO[i] = outO[i] + nOri;
        while( outO[i] >= nOri )
            outO[i] = outO[i] - nOri;
        */
    }
}
/*!
 * This sub-routine computes the velocity vector, given a magnitude, a unit normal vector from the
 * point on the surface where the regolith is lofted from, and the two conic angles which describe
 * the velocity vector's direction relative to the normal vector. A backwards approach is used
 * to go from the velocity vector in the final rotated intermediate frame back to the body fixed
 * frame. More details are given in the thesis report and author's personal notes.
 *
 */
void computeRegolithVelocityVector( std::vector< double > regolithPositionVector,
                                    const double velocityMagnitude,
                                    const double coneAngleAzimuth,
                                    const double coneAngleDeclination,
                                    std::vector< double > &unitNormalVector,
                                    std::vector< double > &regolithVelocityVector )
{
    // form the velocity vector, assuming that the intermediate frame's z-axis, on the surface of
    // the asteroid, is along the final velocity vector
    regolithVelocityVector[ 0 ] = 0.0;
    regolithVelocityVector[ 1 ] = 0.0;
    regolithVelocityVector[ 2 ] = velocityMagnitude;

    // get the rotatin matrix to go from the rotated intermediate frame back to the initial
    // frame where the z-axis was along the normal axis and the x-axis was pointing towards north
    // direction
    std::vector< std::vector< double > > zBasicRotationMatrix
            { { std::cos( coneAngleAzimuth ), std::sin( coneAngleAzimuth ), 0.0 },
              { -std::sin( coneAngleAzimuth ), std::cos( coneAngleAzimuth ), 0.0 },
              { 0.0, 0.0, 1.0 } };

    std::vector< std::vector< double > > yBasicRotationMatrix
            { { std::cos( coneAngleDeclination ), 0.0, -std::sin( coneAngleDeclination ) },
              { 0.0, 1.0, 0.0 },
              { std::sin( coneAngleDeclination ), 0.0, std::cos( coneAngleDeclination ) } };

    std::vector< std::vector< double > > nonTransposedRotationMatrix( 3, std::vector< double > ( 3 ) );

    matrixMultiplication( yBasicRotationMatrix,
                          zBasicRotationMatrix,
                          nonTransposedRotationMatrix,
                          3,
                          3,
                          3,
                          3 );

    std::vector< std::vector< double > > intermediateFrameRotationMatrix( 3, std::vector< double > ( 3 ) );

    matrixTranspose( nonTransposedRotationMatrix, intermediateFrameRotationMatrix );

    std::vector< std::vector< double > > rotatedIntermediateFrameVelocityVector
                { { regolithVelocityVector[ 0 ] },
                  { regolithVelocityVector[ 1 ] },
                  { regolithVelocityVector[ 2 ] } };

    std::vector< std::vector< double > > intermediateFrameVelocityVector( 3, std::vector< double > ( 1 ) );

    matrixMultiplication( intermediateFrameRotationMatrix,
                          rotatedIntermediateFrameVelocityVector,
                          intermediateFrameVelocityVector,
                          3,
                          3,
                          3,
                          1 );

    // now obtain the basis vectors for the intermediate frame expressed in the
    // body fixed frame coordinates
    std::vector< double > xUnitVector( 3 );
    std::vector< double > yUnitVector( 3 );
    std::vector< double > zUnitVector( 3 );

    zUnitVector = unitNormalVector;

    std::vector< double > bodyFrameZUnitVector { 0.0, 0.0, 1.0 };

    // get the intermediate RTN frame at the surface point
    std::vector< double > unitR = normalize( regolithPositionVector );

    std::vector< double > unitT = normalize( crossProduct( unitR, bodyFrameZUnitVector ) );

    // get the x basis vector, pointing to north
    xUnitVector = normalize( crossProduct( unitT, zUnitVector ) );

    // get the y basis vector
    yUnitVector = normalize( crossProduct( zUnitVector, xUnitVector ) );

    std::vector< double > zPrincipalAxisBodyFrame { 0.0, 0.0, 1.0 };
    std::vector< double > zNegativePrincipalAxisBodyFrame { 0.0, 0.0, -1.0 };

    // check if the position vector is along the poles
    const double positionDotPrincipalZ
            = dotProduct( normalize( regolithPositionVector ), zPrincipalAxisBodyFrame );
    const double positionDotNegativePrincipalZ
            = dotProduct( normalize( regolithPositionVector ), zNegativePrincipalAxisBodyFrame );
    if( positionDotPrincipalZ == 1.0 )
    {
        // the position vector is pointing to the poles, hence x basis vector pointing to the north
        // direction wouldn't work
        xUnitVector = { 1.0, 0.0, 0.0 };
        yUnitVector = { 0.0, 1.0, 0.0 };
    }
    else if( positionDotNegativePrincipalZ == 1.0 )
    {
        xUnitVector = { -1.0, 0.0, 0.0 };
        yUnitVector = { 0.0, 1.0, 0.0 };
    }

    // put the basis vectors in a 3x3 matrix
    std::vector< std::vector< double > > intermediateFrameBasisMatrix
            { { xUnitVector[ 0 ], yUnitVector[ 0 ], zUnitVector[ 0 ] },
              { xUnitVector[ 1 ], yUnitVector[ 1 ], zUnitVector[ 1 ] },
              { xUnitVector[ 2 ], yUnitVector[ 2 ], zUnitVector[ 2 ] } };

    std::vector< std::vector< double > > bodyFrameVelocityVector( 3, std::vector< double >( 1 ) );

    matrixMultiplication( intermediateFrameBasisMatrix,
                          intermediateFrameVelocityVector,
                          bodyFrameVelocityVector,
                          3,
                          3,
                          3,
                          1 );

    // return the final regolith velocity vector, expressed in body frame coordinates
    regolithVelocityVector[ 0 ] = bodyFrameVelocityVector[ 0 ][ 0 ];
    regolithVelocityVector[ 1 ] = bodyFrameVelocityVector[ 1 ][ 0 ];
    regolithVelocityVector[ 2 ] = bodyFrameVelocityVector[ 2 ][ 0 ];
}
Esempio n. 7
0
int main(int argc, char **argv){
  
  //LOCAL VARIABLE DEF BLOCK===========================================
  image_ptr imagePtr;
  float subimg[sis][sis]; //space for subimage
  int rows, cols, type;
  int i, j, k, u, v, count; //counter variables
  int offset; //to keep track of values put into subImagePtr
  float scale; //to calcule img size
  int rowsize;
  int rowblock, colblock, totalblock; //number of sub blocks needed for image
  //float Z[1000000]; //this will be the compressed image
  unsigned char writeme[1000000]; //this is the unsigned char to write to file
  unsigned char childOut[100000]; //this is the unsigned char used for child output
  //int zc = 0; //counter for Z
  int wc = 0; //counter for writeme
  int dir; //direction of zig zag 0 = down 1 = up
  int zeros = 0; //holds the number of zeros for "percent zeros" calculation
  int total = 0; //total number of bits used in "percent zeros" calculation
  int tmp; //used in float to unsigned char conversion
  int numOfChildren = 0;
  int childBlock = 0;
  
  //arrays for math
  float C[sis][sis] = {
    {0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536},
    {0.4904, 0.4157, 0.2778, 0.0975, -0.0975, -0.2778, -0.4157, -0.4904},
    {0.4619, 0.1913, -0.1913, -0.4619, -0.4619, -0.1913, 0.1913, 0.4619},
    {0.4157, -0.0975, -0.4904, -0.2778, 0.2778, 0.4904, 0.0975, -0.4157},
    {0.3536, -0.3536, -0.3536, 0.3536, 0.3536, -0.3536, -0.3536, 0.3536},
    {0.2778, -0.4904, 0.0975, 0.4157, -0.4157, -0.0975, 0.4904, -0.2778},
    {0.1913, -0.4619, 0.4619, -0.1913, -0.1913, 0.4619, -0.4619, 0.1913},
    {0.0975, -0.2778, 0.4157, -0.4904, 0.4904, -0.4157, 0.2778, -0.0975}};
  
  float CT[sis][sis] = {
    {0.3536, 0.4904, 0.4619, 0.4157, 0.3536, 0.2778, 0.1913, 0.0975},
    {0.3536, 0.4157, 0.1913, -0.0975, -0.3536, -0.4904, -0.4619, -0.2778},
    {0.3536, 0.2778, -0.1913, -0.4904, -0.3536, 0.0975, 0.4619, 0.4157},
    {0.3536, 0.0975, -0.4619, -0.2778, 0.3536, 0.4157, -0.1913, -0.4904},
    {0.3536, -0.0975, -0.4619, 0.2778, 0.3536, -0.4157, -0.1913, 0.4904},
    {0.3536, -0.2778, -0.1913, 0.4904, -0.3536, -0.0975, 0.4619, -0.4157},
    {0.3536, -0.4157, 0.1913, 0.0975, -0.3536, 0.4904, -0.4619, 0.2778},
    {0.3536, -0.4904, 0.4619, -0.4157, 0.3536, -0.2778, 0.1913, -0.0975}};
  
  //same for array Q
  float Q[sis][sis] = {
    {8, 16, 24, 32, 40, 48, 56, 64},
    {16, 24, 32, 40, 48, 56, 64, 72},
    {24, 32, 40, 48, 56, 64, 72, 80},
    {32, 40, 48, 56, 64, 72, 80, 88},
    {40, 48, 56, 64, 72, 80, 88, 96},
    {48, 56, 64, 72, 80, 88, 96, 104},
    {56, 64, 72, 80, 88, 95, 104, 112},
    {64, 72, 80, 88, 96, 104, 112, 120}};
  
  float q[sis][sis];
  for (i = 0; i < 8; i++){
    for (j = 0; j < 8; j++){
      q[i][j] = Q[i][j];
    }
  }
  
  //GET COMMAND LINE INPUTS===========================================
  if (argc != 5){
    printf("wrong inputs: use %s imageIn.ppm imageOut.enc q p\n", argv[0]);
    return 0;
  }
  
  //READ INPUT IMAGE==================================================
  printf("Reading input image. . . \n");
  imagePtr = read_pnm(argv[1], &rows, &cols, &type);
  printf("Image read successfully\n");
  printf("rows=%d, cols=%d, type=%d \n", rows, cols, type);

  int tb; //total blocks to be processed
  int cb = 0; //current block
  int g; //counter
  tb = (rows / sis) * (cols / sis);
  
  //Place image into 2D array
  unsigned char myImg[rows][cols];
  for (i = 0; i < rows; i++){
    for (j = 0; j < cols; j++){
      myImg[i][j] = imagePtr[i*cols+j];
    }
  }
  
  //set q array to propperly scaled value, based on input
  int qin;
  qin = atoi(argv[3]);
  intTimesMatrix(q, qin);

  // clip q to be between 0 and 255
  for (u = 0; u < sis; u++){
    for (v = 0; v < sis; v++){
      if (q[u][v] > 254)
	q[u][v] = 254;
    }
  }
  
  //get p
  int p;
  p = atoi(argv[4]);

  //create tmp variables for preforming math operations
  float CX[sis][sis];
  float Y[sis][sis];
  int r, c;
  
  //get row and col characters - assumes that image is smaller than 1000x1000
  int row1, row2, row3;
  int col1, col2, col3;
  row1 = rows / 100;
  row2 = (rows - (row1 * 100)) / 10;
  row3 = (rows - (row1 * 100)) - (row2 * 10);
  col1 = cols / 100;
  col2 = (cols - col1 * 100) / 10;
  col3 = (cols - col1 * 100) - col2 * 10;
  
  //build header
  writeme[wc++] = row1 + '0';
  writeme[wc++] = row2 + '0';
  writeme[wc++] = row3 + '0';
  writeme[wc++] = '$'; //end of block character
  writeme[wc++] = col1 + '0';
  writeme[wc++] = col2 + '0';
  writeme[wc++] = col3 + '0';
  writeme[wc++] = '$';
  writeme[wc++] = '8';
  writeme[wc++] = '$';
  writeme[wc++] = '8';
  writeme[wc++] = '$';
  writeme[wc++] = qin + '0';
  writeme[wc++] = '$';
  writeme[wc++] = '0';
  writeme[wc++] = '0';
  writeme[wc++] = '$';
  //create placeholder to put estimated size in later
  for (i = 0; i < 7; i++){
    writeme[wc++] = '0';
  }
  writeme[wc++] = '$';
  
  //STEP THROUGH INPUT IMAGE===========================================
  int makepipes;
  float tm;
  int mt;
  int pipefds[2*p];
  int pid;
  for (i = 0; i < rows; i = i + 8){
    for (j = 0; j < cols; j = j + 8){

      for (u = 0; u < sis; u++){
	for (v = 0; v < sis; v++){
	  
	  //cast to float to make math operations possible and level off for proper DCT values
	  mt = (int) myImg[i+u][j+v];
	  tm = (float) mt;
	  subimg[u][v] = tm - 128;
	  //make sure Y and CX are clear
	  Y[u][v] = 0;
	  CX[u][v] = 0;
	  
	}
      }

      cb++; //increment current block

      if (numOfChildren  == 0){ 
	//build all necessary pipes
	if (tb - cb < p){
	  //only make amount of pipes necessary
	  makepipes = tb - cb + 1;
	} else {
	  makepipes = p;
	}
	
	for (g = 0; g < makepipes; g++){
	  if (pipe(pipefds + g*2) < 0){
	    perror("Pipe");
	    exit(1);
	  }
	}
      } 
      
      numOfChildren++;
      if ((pid = fork()) == 0){
	//zero means child

	//Perform first step of matrix multiplication CX = C*subimg
	matrixMultiplication(C, subimg, CX);
	
	//Perform second step of matrix multiplication Y = CX*CT
	matrixMultiplication(CX, CT, Y);
	
	//quantize Y by dividing element by element with q
	eleByEleMatrixDiv(Y, q);
	
	//undo the (-128)
	for (u = 0; u < sis; u++){
	  for (v = 0; v < sis; v++){
	    Y[u][v] = Y[u][v] + 128;
	  }
	}

	//preform zig zag on Y, sore flat result in Z
	r = 0; //current row
	c = 0; //current col
	count = 0;
	dir = 0;
      
	//loop to preform zig zagging
	while (count < 64){
	  if (Y[r][c] < 128.4 && Y[r][c] > 127.5){
	    //count zeros
	    zeros = (64 - count); //should probably just send this back to the parent
	    //REMEMBER TO ADD ZEROS BACK TOGETHER WHEN READING BACK IN
	    total = 64;
	    //AND ADD TOTAL
	    break;
	  }
	
	  if (r == 0 && c < 7){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c++;
	  
	    if (Y[r][c] < 128.4 && Y[r][c] > 127.5){
	      zeros = (64 - count);
	      total = 64;
	      break;
	    }
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c--; r++;
	    dir = 0;
	  
	  } else if (c == 0 && r < 7){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    r++; 
	  
	    if (Y[r][c] < 128.4 && Y[r][c] > 127.5){
	      zeros = (64 - count);
	      total = 64;
	      break;
	    }
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    r--; c++;
	    dir = 1;
	  
	  } else if ( r == 7){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c++;
	  
	    if (Y[r][c] < 128.4 && Y[r][c] > 127.5){
	      //count zeros
	      zeros = (64 - count);
	      total = 64;
	      break;
	    }
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c++; r--;
	    dir = 1;
	  
	  } else if ( c == 7){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    r++; 

	    if (Y[r][c] < 128.4 && Y[r][c] > 127.5){
	      //count zeros
	      zeros = (64 - count);
	      total = 64;
	      break;
	    }
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    r++; c--;
	    dir = 0;
	  
	  } else if (dir == 0){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c--; r++;
	  
	  } else if (dir == 1){
	  
	    tmp = (int) Y[r][c];
	    childOut[count++] = (unsigned char) tmp;
	    c++; r--;
	  
	  }
	}
	childOut[count++] = '$';

	//need to add in percent zeros and block position
	//actually might not need to worry about positioning (use pipes to keep track)
      
	unsigned char results[count];
	for (g = 0; g < count; g++){
	  results[g] = childOut[g];
	}

	//return data
	//could add several '$' to mark end of transmitted data
	write(pipefds[(numOfChildren-1)*2+1], results, sizeof(results));

	//kill child
	exit(0);
	
      } else if (pid == -1) {
	
	//fork error
	printf("Fork error\n");
	exit(1);
	
      } else {

	//this is the parent
	if (numOfChildren >= makepipes){
	  //this means all children are made, need to get results
	  //not sure how to make sure they are all finished or not?
	  //wonder if it waits for something to be written?
	  unsigned char tmpin[100];
	  //get data
	  for (g = 0; g < makepipes; g++){
	    read(pipefds[2*g], tmpin, sizeof(tmpin));
	    int h = 0;
	    while (tmpin[h] != '$'){
	      writeme[wc++] = tmpin[h++];
	      if (h > 99){
		printf("something probably went wrong");
		break;
	      }
	    }
	    writeme[wc++] = '$';
	    //h is going to be equivilent to (64 - zeros)
	    zeros = zeros + (64 - h);
	    total = total + 64;
	  }
	  
	  //close pipes
	  for (g = 0; g < 2 * makepipes; g++){
	    close(pipefds[g]);
	  }
	  // all children should be dead at this point
	  numOfChildren = 0;
	}
      }
      
    }
  }
  
  //change percent zeros in write me
  float pz;
  printf("This is total: %d\n", total);
  printf("This is zeros: %d\n", zeros);
  pz = (float) zeros / total;
  printf("Percent Zeros: %f\n", pz);
  pz = (int) (pz * 100);
  int pz1;
  pz1 = pz / 10;
  int pz2;
  pz2 = pz - pz1 * 10;
  writeme[14] = pz1 + '0';
  writeme[15] = pz2 + '0';
  
  //change estimated size
  //estimated size is zc, so get each element then plug into Z[17 - 24]
  int zc1, zc2, zc3, zc4, zc5, zc6, zc7;
  zc1 = wc / 1000000;
  zc2 = (wc - zc1 * 1000000) / 100000;
  zc3 = (wc - zc1 * 1000000 - zc2 * 100000) / 10000;
  zc4 = (wc - zc1 * 1000000 - zc2 * 100000 - zc3 * 10000) / 1000;
  zc5 = (wc - zc1 * 1000000 - zc2 * 100000 - zc3 * 10000 - zc4 * 1000) / 100;
  zc6 = (wc - zc1 * 1000000 - zc2 * 100000 - zc3 * 10000 - zc4 * 1000 - zc5 * 100) / 10;
  zc7 = (wc - zc1 * 1000000 - zc2 * 100000 - zc3 * 10000 - zc4 * 1000 - zc5 * 100 - zc6  * 10);
  
  writeme[17] = zc1 + '0';
  writeme[18] = zc2 + '0';
  writeme[19] = zc3 + '0';
  writeme[20] = zc4 + '0';
  writeme[21] = zc5 + '0';
  writeme[22] = zc6 + '0';
  writeme[23] = zc7 + '0';

  //write file
  FILE *f = fopen(argv[2], "w");
  if (f == NULL){
    printf("Error opening file\n");
    return 0;
  }

  for (i = 0; i < wc; i++){
    fprintf(f, "%c", writeme[i]);
  }
  fclose(f);
  
}