/* * dither each pixel to the nearest value in the new number of bits * using error diffusion */ Image* ip_quantize_fs (Image* src, int bitsPerChannel) { Image* tempImage = ip_quantize_simple(src, bitsPerChannel); //Image* tempImage = src; double errors[4]; double errorRed = 0.0; double errorGreen = 0.0; double errorBlue = 0.0; for (int i = 0; i < src->getWidth(); ++i) { for (int j = 0; j < src->getHeight(); ++j) { errorRed = src->getPixel_(i, j, 0) - tempImage->getPixel_(i,j, 0); tempImage->setPixel_(i+1, j, 0, (7.0/16.0*errorRed) + src->getPixel_(i+1,j,0)); tempImage->setPixel_(i-1, j+1, 0, (3.0/16.0*errorRed) + src->getPixel_(i-1,j+1,0)); tempImage->setPixel_(i, j+1, 0, (5.0/16.0*errorRed) + src->getPixel_(i,j+1,0)); tempImage->setPixel_(i+1, j+1, 0, (1.0/16.0*errorRed) + src->getPixel_(i+1,j+1,0)); errorGreen = src->getPixel_(i, j, 1) - tempImage->getPixel_(i,j, 1); tempImage->setPixel_(i+1, j, 1, (7.0/16.0*errorGreen) + src->getPixel_(i+1,j,1)); tempImage->setPixel_(i-1, j+1, 1, (3.0/16.0*errorGreen) + src->getPixel_(i-1,j+1,1)); tempImage->setPixel_(i, j+1, 1, (5.0/16.0*errorGreen) + src->getPixel_(i,j+1,1)); tempImage->setPixel_(i+1, j+1, 1, (1.0/16.0*errorGreen) + src->getPixel_(i+1,j+1,1)); errorBlue = src->getPixel_(i, j, 2) - tempImage->getPixel_(i,j, 2); tempImage->setPixel_(i+1, j, 2, (7.0/16.0*errorBlue) + src->getPixel_(i+1,j,2)); tempImage->setPixel_(i-1, j+1, 2, (3.0/16.0*errorBlue) + src->getPixel_(i-1,j+1,2)); tempImage->setPixel_(i, j+1, 2, (5.0/16.0*errorBlue) + src->getPixel_(i,j+1,2)); tempImage->setPixel_(i+1, j+1, 2, (1.0/16.0*errorBlue) + src->getPixel_(i+1,j+1,2)); tempImage = ip_quantize_simple(tempImage, bitsPerChannel); } } return tempImage; }
void process_func (int value) { Image* resultImage = NULL; static int samplingMode = I_NEAREST; static int gaussianFilterSize = 3; static double gaussianSigma = 1.0; // check if we have an image to process if (!currentImage) { cerr << "Sorry, no image is loaded!" << endl; return; } switch (value) { case M_PROCESS_BLUR_BOX: // enum #6 { int filterSize = getFilterSize(); if (filterSize>0) resultImage = ip_blur_box(currentImage, filterSize); break; } case M_PROCESS_BLUR_GAUSSIAN: // enum #7 { int filterSize = getFilterSize(); if (filterSize<=0) break; double sigma = getPositiveDouble("sigma"); if (sigma>0) resultImage = ip_blur_gaussian(currentImage, filterSize, sigma); break; } case M_PROCESS_BLUR_TRIANGLE: // enum #8 { int filterSize = getFilterSize(); if (filterSize>0) resultImage = ip_blur_triangle(currentImage, filterSize); break; } case M_PROCESS_BRIGHTEN: // enum #9 { double alpha = getDouble("alpha"); resultImage = ip_brighten(currentImage, alpha); break; } case M_PROCESS_COLOR_SHIFT: // enum #10 resultImage=ip_color_shift(currentImage); break; case M_PROCESS_CONTRAST: // enum #11 { double alpha=getDouble("alpha"); resultImage = ip_contrast(currentImage, alpha); break; } case M_PROCESS_COMPOSITE: // enum #12 { char filename[MAX_NAME]; // we don't do a lot of checks here; i.e. second image and // mask valid images and the same size as current image if (!quietMode) cerr << "Enter filename of second image (string - no spaces) : "; cin >> filename; Image* secondImage = new Image(); secondImage->read(filename); if (!quietMode) cerr << "Enter filename of mask (string - no spaces) : "; cin >> filename; Image* mask = new Image(); mask->read(filename); checkStream(cin); resultImage = ip_composite(currentImage, secondImage, mask); delete secondImage; delete mask; break; } case M_PROCESS_CROP: // enum #13 { int x0, y0, x1, y1; if (!quietMode) { cerr << "Current image width and height: " << currentImage->getWidth()-1 << " " << currentImage->getHeight()-1 << endl; cerr << "Enter region to crop (left top right bottom (ints)) : "; } cin >> x0 >> y0 >> x1 >> y1; checkStream(cin); if (x0>=0 || x0<x1 || x1<currentImage->getWidth() || y0>=0 || y0<y1 || y1<currentImage->getHeight()) { resultImage = ip_crop(currentImage, x0,y0,x1,y1); } else { cerr<< "Invalid region." << endl; } break; } case M_PROCESS_EDGE_DETECT: // enum #14 resultImage = ip_edge_detect(currentImage); break; case M_PROCESS_EXTRACT: // enum #15 { int channel = getInt("channel [0,2]"); if (channel<0 || channel>2) { cerr << "Invalid channel."<< endl; } else { resultImage = ip_extract(currentImage, channel); } break; } case M_PROCESS_FUN_WARP: // enum #16 resultImage = ip_fun_warp(currentImage,samplingMode); break; case M_PROCESS_GREY: // enum #17 resultImage = ip_grey(currentImage); break; case M_PROCESS_IMAGE_SHIFT: // enum #18 { double dx = getDouble("dx"); double dy = getDouble("dy"); resultImage = ip_image_shift(currentImage,dx, dy); break; } case M_PROCESS_INVERT: // enum #19 resultImage = ip_invert(currentImage); break; case M_PROCESS_MISC: // enum #20 resultImage = ip_misc(currentImage); break; case M_PROCESS_QUANTIZE_SIMPLE: // enum #21 { int bitsPerChannel = getInt("bits per channel [1,8]"); if (bitsPerChannel<=0 || bitsPerChannel>8) { cerr << "Invalid number bits." << endl; } else { resultImage = ip_quantize_simple(currentImage, bitsPerChannel); } break; } case M_PROCESS_QUANTIZE_ORDERED: //enum #22 { int bitsPerChannel = getInt("bits per channel [1,8]"); if (bitsPerChannel<=0 || bitsPerChannel>8) { cerr << "Invalid number bits." << endl; } else { resultImage = ip_quantize_ordered(currentImage, bitsPerChannel); } break; } case M_PROCESS_QUANTIZE_FLOYD_STEINBERG: // enum #23 { int bitsPerChannel = getInt("bits per channel [1,8]"); if (bitsPerChannel<=0 || bitsPerChannel>8) { cerr << "Invalid number bits." << endl; } else { resultImage = ip_quantize_fs(currentImage, bitsPerChannel); } break; } case M_PROCESS_ROTATE: // enum #24 { if (!quietMode) { cerr<< "Current image width/height: " << currentImage->getWidth()-1 << " " << currentImage->getHeight()-1 << endl; } double theta = getDouble("angle"); double x = getDouble("point x"); double y = getDouble("point y"); resultImage = ip_rotate(currentImage, theta, x, y, samplingMode, gaussianFilterSize, gaussianSigma); break; } case M_PROCESS_SATURATE: // enum #25 { double alpha = getDouble("alpha"); resultImage = ip_saturate(currentImage, alpha); break; } case M_PROCESS_SCALE: // enum #26 { double xFactor = getDouble("scale factor for x"); double yFactor = getDouble("scale factor for y"); resultImage = ip_scale(currentImage, xFactor, yFactor, samplingMode, gaussianFilterSize, gaussianSigma); break; } case M_PROCESS_SET_SAMPLING_BILINEAR: // enum #27 samplingMode=I_BILINEAR; break; case M_PROCESS_SET_SAMPLING_NEAREST: // enum #28 samplingMode=I_NEAREST; break; case M_PROCESS_SET_SAMPLING_GAUSSIAN: // enum #29 gaussianFilterSize=getInt("filter size (positive, even integer)"); if (gaussianFilterSize%2!=0 || gaussianFilterSize<=0) { gaussianFilterSize=3; cerr<<"Invalid value, using default size of 3"<<endl; } gaussianSigma=getDouble("sigma (non-negative)"); if (gaussianSigma <0) { gaussianSigma=1; cerr<<"Invalid value, using default sigma of 1"<<endl; } samplingMode=I_GAUSSIAN; break; case M_PROCESS_THRESHOLD: // enum #23 { double threshold=getDouble("threshold [0,1]"); resultImage = ip_threshold(currentImage, threshold); break; } default: break; } if (resultImage != NULL) { delete currentImage; currentImage = resultImage; if (currentImage->getWidth() != window_width || currentImage->getHeight() != window_height) reshape(currentImage->getWidth(), currentImage->getHeight()); if (!quietMode) cerr << "done!" << endl; if (!textMode) glutPostRedisplay(); } }