void pixelToGrayscale(int& r, int& g, int& b) {
int gray = (0.21 * r) + (0.72 * g) + (0.07 * b);
r = gray;
g = gray;
b = gray;
}
void pixelToBinary(int& r, int& g, int& b) {
int gray = (0.21 * r) + (0.72 * g) + (0.07 * b);
if (gray <= 127){
r = 0;
g = 0;
b = 0;
return;
}
r = 255;
g = 255;
b = 255;
}
int binToInt(fstream& stream, int offset) {
int result = 0,
base = 1;
stream.seekg(offset);
for (int i = 0; i < 4; i++){
result += (stream.get() * base);
base *= 256;
}
return result;
}
void main() {
try{
//get the file name from the user (must be in the same directory)
string fileName, outputFileName;
cout << "Input file: ";
cin >> fileName;
cout << "Output file: ";
cin >> outputFileName;
//open the file in binary mode and copy the source to the destination
ifstream inputFile;
fstream stream;
inputFile.open(fileName.c_str(), ios::binary);
stream.open(outputFileName.c_str(), ios::out | ios::binary);
stream << inputFile.rdbuf();
stream.close();
stream.open(outputFileName.c_str(), ios::in | ios::out | ios::binary);
//read the basic info about the image
int fileSize = binToInt(stream, 2),
startOffset = binToInt(stream, 10),
width = binToInt(stream, 18),
height = binToInt(stream, 22),
scanlineWidth = width * 3,
padding = 0,
pixelOffset = scanlineWidth % 4;
//fix the padding
if (pixelOffset != 0){
padding = 4 - pixelOffset;
}
//ask the user what should be done with it
string input;
cout << "What should we do with the image (type the letter in)?\na. Convert to grayscale\nb. Convert to black and white\nYour choice: ";
cin >> input;
//point to the right function based on the user's input
void(*processPixel)(int&, int&, int&);
if (input == "a"){
processPixel = &pixelToGrayscale;
}
else if (input == "b"){
processPixel = &pixelToBinary;
}
else{
cout << "Invalid input\n";
return 0;
}
//process the image
cout << "Processing... /";
stream.seekg(startOffset);
for (int i = 0; i < height; i++){
//fancy flipping slash
cout << '\b';
if ((i % 2) == 0){
cout << '/';
}
else {
cout << '\\';
}
for (int j = 0; j < width; j++){
//read the pixel
int pixelPosition = stream.tellg(),
blue = stream.get(),
green = stream.get(),
red = stream.get();
processPixel(red, green, blue); //process the pixel
//write the pixel
stream.seekp(pixelPosition);
stream.put(blue);
stream.put(green);
stream.put(red);
}
stream.seekg(padding, ios::cur); //skip the padding at the end of the scan line
}