//Chad Williamson #include #include #include #include #include //prototype void writeFile(std::string name, unsigned char** image, int height, int width, std::string opName); unsigned char normalizedResult(double input, int sizeOfOperatorMatrix); int main() { //variables std::string operation[8] = { "3x3_vertical", "3x3_horizontal", "3x3_gradient", "3x3_edge" , "5x5_vertical", "5x5_horizontal", "5x5_gradient", "5x5_edge" }; int boundarySize[8] = {1,1,1,1,2,2,2,2}; const double pi = 3.14159265358979323846; std::string thisNameStr = "default.raw"; int thisWidth = 500; int thisHeight = 325; std::cout << "Enter full image name: "; std::cin >> thisNameStr; std::cout << "Enter width: "; std::cin >> thisWidth; std::cout << "Enter height: "; std::cin >> thisHeight; std::string outputStr = "default.raw"; std::cout << "FILE: " << thisNameStr << ". Width: " << thisWidth << ", Height: " << thisHeight << std::endl; const char* thisName = thisNameStr.c_str(); const char* outputName = outputStr.c_str(); //file FILE* thisImage; //initial 1D buffer to load raw image unsigned char* buffer = new unsigned char[(thisHeight * thisWidth)]; //2D array for image buffer unsigned char** imageBuffer = new unsigned char* [thisHeight]; for (int i = 0; i < thisHeight; i++) { imageBuffer[i] = new unsigned char[thisWidth]; } //2d array to hold the resulting image unsigned char** resultBuffer = new unsigned char* [thisHeight]; for (int i = 0; i < thisHeight; i++) { resultBuffer[i] = new unsigned char[thisWidth]; } size_t result; thisImage = fopen(thisName, "rb"); if (thisImage != NULL) { //image successfully opened std::cout << "Opening " << thisName << std::endl; // copy the file into the initial buffer: result = fread(buffer, 1, ((thisHeight * thisWidth)), thisImage); //copy the 1D raw data in buffer to the 2D array for (int i = 0; i < thisHeight; i++) { for (int j = 0; j < thisWidth; j++) { (imageBuffer[i])[j] = buffer[(i * thisWidth) + j]; } } // values for edge detection // int pixelValues[5][5] = { 0 }; double result = 0.0; double compResult = 0.0; //main code for the operators. loop through 8 times to produce different outputs //1st loop: 3x3 vertical, 2nd loop: 3x3 horizontal, 3rd loop: 3x3 gradient, 4th loop: 3x3 edge, 5th loop: 5x5 vertrical, 6th loop: 5x5 horizontal, 7th loop: 5x5 gradient, 8th loop: 5x5 edge for (int run = 0; run < 8; run++) { for (int i = 0; i < thisHeight; i++) { //ignore border rows if ((i >= boundarySize[run])&&(i < (thisHeight - boundarySize[run]))) { //read through each row for (int j = 0; j < thisWidth; j++) { //ignore the left and right edges of the image if ((j >= boundarySize[run])&&(j < (thisWidth - boundarySize[run]))) { //store values for the operator if ((run != 3)&&(run != 7)) { (resultBuffer[i])[j] = ((imageBuffer[i])[j]); } pixelValues[1][1] = int ((imageBuffer[i - 1])[j - 1]); pixelValues[1][2] = int ((imageBuffer[i - 1])[j]); pixelValues[1][3] = int ((imageBuffer[i - 1])[j + 1]); pixelValues[2][1] = int ((imageBuffer[i])[j - 1]); pixelValues[2][2] = int ((imageBuffer[i])[j]); pixelValues[2][3] = int ((imageBuffer[i])[j + 1]); pixelValues[3][1] = int ((imageBuffer[i + 1])[j - 1]); pixelValues[3][2] = int ((imageBuffer[i + 1])[j]); pixelValues[3][3] = int ((imageBuffer[i + 1])[j + 1]); if (run > 3) { pixelValues[0][0] = int ((imageBuffer[i - 2])[j - 2]); pixelValues[0][1] = int ((imageBuffer[i - 2])[j - 1]); pixelValues[0][2] = int ((imageBuffer[i - 2])[j]); pixelValues[0][3] = int ((imageBuffer[i - 2])[j + 1]); pixelValues[0][4] = int ((imageBuffer[i - 2])[j + 2]); pixelValues[1][0] = int ((imageBuffer[i - 1])[j - 2]); pixelValues[2][0] = int ((imageBuffer[i])[j - 2]); pixelValues[3][0] = int ((imageBuffer[i + 1])[j - 2]); pixelValues[1][4] = int ((imageBuffer[i - 1])[j + 2]); pixelValues[2][4] = int ((imageBuffer[i])[j + 2]); pixelValues[3][4] = int ((imageBuffer[i + 1])[j + 2]); pixelValues[4][0] = int ((imageBuffer[i + 2])[j - 2]); pixelValues[4][1] = int ((imageBuffer[i + 2])[j - 1]); pixelValues[4][2] = int ((imageBuffer[i + 2])[j]); pixelValues[4][3] = int ((imageBuffer[i + 2])[j + 1]); pixelValues[4][4] = int ((imageBuffer[i + 2])[j + 2]); } switch (run) { case 0: //vertical 3x3 result = (pixelValues[1][1] * -1) + (pixelValues[2][1] * -2) + (pixelValues[3][1] * -1) + (pixelValues[1][3]) + (pixelValues[2][3] * 2) + (pixelValues[3][3]); (resultBuffer[i])[j] = normalizedResult(result, 4); break; case 1: //horizontal 3x3 result = (pixelValues[1][1] * -1) + (pixelValues[1][2] * -2) + (pixelValues[1][3] * -1) + (pixelValues[3][1]) + (pixelValues[3][2] * 2) + (pixelValues[3][3]); (resultBuffer[i])[j] = normalizedResult(result, 4); break; case 2: //3x3 gradient result = (pixelValues[1][1] * -1) + (pixelValues[2][1] * -2) + (pixelValues[3][1] * -1) + (pixelValues[1][3]) + (pixelValues[2][3] * 2) + (pixelValues[3][3]); compResult = (pixelValues[1][1] * -1) + (pixelValues[1][2] * -2) + (pixelValues[1][3] * -1) + (pixelValues[3][1]) + (pixelValues[3][2] * 2) + (pixelValues[3][3]); (resultBuffer[i])[j] = (((abs(result) / 4) + (abs(compResult) / 4)) / 2); break; case 3: if ((((resultBuffer[i][j] > resultBuffer[i - 1][j]) && (resultBuffer[i][j] > resultBuffer[i + 1][j])) && (resultBuffer[i][j] + resultBuffer[i + 1][j] + resultBuffer[i - 1][j] > 40)) || (((resultBuffer[i][j] > resultBuffer[i][j - 1]) && (resultBuffer[i][j] > resultBuffer[i][j + 1])) && (resultBuffer[i][j] + resultBuffer[i][j + 1] + resultBuffer[i][j - 1] > 40))) { resultBuffer[i][j] = 255; } else { resultBuffer[i][j] = 0; } break; case 4: //vertical 5x5 result = (pixelValues[0][0] * -1) + (pixelValues[0][1] * -2) + (pixelValues[0][3] * 2) + (pixelValues[0][4] * 1) + (pixelValues[1][0] * -2) + (pixelValues[1][1] * -4) + (pixelValues[1][3] * 4) + (pixelValues[1][4] * 2) + (pixelValues[2][0] * -4) + (pixelValues[2][1] * -8) + (pixelValues[2][3] * 8) + (pixelValues[2][4] * 4) + (pixelValues[3][0] * -2) + (pixelValues[3][1] * -4) + (pixelValues[3][3] * 4) + (pixelValues[3][4] * 2) + (pixelValues[4][0] * -1) + (pixelValues[4][1] * -2) + (pixelValues[4][3] * 2) + (pixelValues[4][4] * 1); (resultBuffer[i])[j] = normalizedResult(result, 30); break; case 5: //horizontal 5x5 result = (pixelValues[0][0] * -1) + (pixelValues[0][1] * -2) + (pixelValues[0][2] * -4) + (pixelValues[0][3] * -2) + (pixelValues[0][4] * -1) + (pixelValues[1][0] * -2) + (pixelValues[1][1] * -4) + (pixelValues[1][2] * -8) + (pixelValues[1][3] * -4) + (pixelValues[1][4] * -2) + (pixelValues[3][0] * 2) + (pixelValues[3][1] * 4) + (pixelValues[3][2] * 8) + (pixelValues[3][3] * 4) + (pixelValues[3][4] * 2) + (pixelValues[4][0] * 1) + (pixelValues[4][1] * 2) + (pixelValues[4][2] * 4) + (pixelValues[4][3] * 2) + (pixelValues[4][4] * 1); (resultBuffer[i])[j] = normalizedResult(result, 30); break; case 6: //5x5 gradient result = (pixelValues[0][0] * -1) + (pixelValues[0][1] * -2) + (pixelValues[0][3] * 2) + (pixelValues[0][4] * 1) + (pixelValues[1][0] * -2) + (pixelValues[1][1] * -4) + (pixelValues[1][3] * 4) + (pixelValues[1][4] * 2) + (pixelValues[2][0] * -4) + (pixelValues[2][1] * -8) + (pixelValues[2][3] * 8) + (pixelValues[2][4] * 4) + (pixelValues[3][0] * -2) + (pixelValues[3][1] * -4) + (pixelValues[3][3] * 4) + (pixelValues[3][4] * 2) + (pixelValues[4][0] * -1) + (pixelValues[4][1] * -2) + (pixelValues[4][3] * 2) + (pixelValues[4][4] * 1); compResult = (pixelValues[0][0] * -1) + (pixelValues[0][1] * -2) + (pixelValues[0][2] * -4) + (pixelValues[0][3] * -2) + (pixelValues[0][4] * -1) + (pixelValues[1][0] * -2) + (pixelValues[1][1] * -4) + (pixelValues[1][2] * -8) + (pixelValues[1][3] * -4) + (pixelValues[1][4] * -2) + (pixelValues[3][0] * 2) + (pixelValues[3][1] * 4) + (pixelValues[3][2] * 8) + (pixelValues[3][3] * 4) + (pixelValues[3][4] * 2) + (pixelValues[4][0] * 1) + (pixelValues[4][1] * 2) + (pixelValues[4][2] * 4) + (pixelValues[4][3] * 2) + (pixelValues[4][4] * 1); (resultBuffer[i])[j] = (((abs(result) / 30) + (abs(compResult) / 30)) / 2); break; case 7: if ((((resultBuffer[i][j] > resultBuffer[i - 1][j]) && (resultBuffer[i][j] > resultBuffer[i + 1][j])) && (resultBuffer[i][j] + resultBuffer[i + 1][j] + resultBuffer[i - 1][j] > 30)) || (((resultBuffer[i][j] > resultBuffer[i][j - 1]) && (resultBuffer[i][j] > resultBuffer[i][j + 1])) && (resultBuffer[i][j] + resultBuffer[i][j + 1] + resultBuffer[i][j - 1] > 30))) { resultBuffer[i][j] = 255; } else { resultBuffer[i][j] = 0; } break; } } //leave the outer edge as is else { (resultBuffer[i])[j] = ((imageBuffer[i])[j]); } } } else { //leave top and bottom rows of image as is for (int j = 0; j < thisWidth; j++) { (resultBuffer[i])[j] = (imageBuffer[i])[j]; } } } //end of main code if (run == 3 || run == 7) { for (int i = 1; i < thisHeight - 1; i++) { for (int j = 1; j < thisWidth - 1; j++) { if ((resultBuffer[i - 1][j - 1] == 0)&&(resultBuffer[i - 1][j] == 0)&&(resultBuffer[i - 1][j + 1] == 0)&&(resultBuffer[i][j - 1] == 0)&& (resultBuffer[i][j + 1] == 0)&&(resultBuffer[i + 1][j - 1] == 0)&&(resultBuffer[i + 1][j] == 0)&&(resultBuffer[i + 1][j + 1] == 0)) { resultBuffer[i][j] = 0; } else { //resultBuffer[i][j] = 0; } } } } //write file writeFile(thisNameStr, resultBuffer, thisHeight, thisWidth, operation[run]); } //end of FOR loop that runs through main code //close the files fclose(thisImage); } //not found else { std::cout << "Image not found! Exiting" << std::endl; } //deallocate image buffers delete[] buffer; for (int i = 0; i < thisHeight; i++) { delete[] imageBuffer[i]; delete[] resultBuffer[i]; } delete[] imageBuffer; delete[] resultBuffer; return 0; } //write the 2d array to file. requires pointer to 2d array, name, and file void writeFile(std::string name, unsigned char** image, int height, int width, std::string opName) { //variables int pos = 0; const char* outputName; FILE* writeImage; //1D array that will be written to file unsigned char* storeBuffer = new unsigned char[(height * width)]; //copy the resulting 2D array to a 1D array to be written as a file for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { storeBuffer[(i * width) + j] = image[i][j]; } } //name the file pos = name.find("."); name = (name.substr(0, pos) + "_" + opName + ".raw"); outputName = name.c_str(); //write image std::cout << "Writing to: " << outputName << std::endl; writeImage = fopen(outputName, "wb"); fwrite(storeBuffer, 1, (height * width), writeImage); //close file and deallocate delete[] storeBuffer; fclose(writeImage); } unsigned char normalizedResult(double input, int sizeOfOperatorMatrix) { //divide by 4 to get range from 0 to 255, positive or negative input = input / sizeOfOperatorMatrix; //center around 128 if (input < 0) { //get value of -127 to 0 input = input / 1.9921875; } else { //get value of 0 to 126 input = input / 2.02381; } input += 128; return unsigned char(input); }