Problem: Gaussian Spatial Weighted Image Metrics

The problem aims to create C++ functions for image data processing and analysis, involving file path search, format validation (e.g., BMP), pixel data handling, Gaussian spatial weighting, and computation of metrics like weighted MSE, PSNR, SSIM, variance, entropy, and SNR to enable image quality assessment and statistical analysis.


Input/Output: The problem accepts inputs: pairs of BMP filenames (as strings for 12.1–12.3), a single BMP filename (as a string for 12.4–12.5), and an integer band number (for 12.6). Functions search for BMP/binary files in paths including "test_data/", "../test_data/", "../../test_data/", "substep/test_data/", or the current directory. For BMPs, they validate the "BM" signature, read file/info headers and pixel data (handling 4-byte row alignment and 8-bit color tables), and flip rows vertically. For the binary file (12.6), they use fixed 600x600 dimensions and read the specified band. Each function returns a double: 12.1 computes Gaussian distance-weighted MSE; 12.2 computes PSNR (20*log10(255/sqrt(MSE))) or 100.0 on errors; 12.3 computes SSIM with c1=0.01 and c2=0.03; 12.4 returns the square root of Gaussian-weighted variance; 12.5 returns entropy from a Gaussian-weighted histogram; 12.6 returns 20*log10(mean/sqrt(weighted variance)) for the binary band. Errors (file not found, invalid BMP, size mismatch) return -1.0, 100.0, or 0.0 as specified.

Required dependencies:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <algorithm>
using namespace std;

Sub-steps:
step_number: 1
step_description_prompt: Please write a C++ function named problem_12_1 that calculates the weighted Mean Squared Error (MSE) between two BMP images. The function takes two string parameters representing the filenames of the BMP files and returns a double value as the result.

Function definition: double problem_12_1(const string& file1, const string& file2);

Algorithm steps:
1. For each input filename, try to find the file by checking paths in the order: "test_data/" + filename, "substep/test_data/" + filename, "../test_data/" + filename, "../../test_data/", and the filename directly. If either file is not found, output "Error: Cannot find data file" to cerr and return -1.0.
2. Open the found files in binary mode. Read BMPFileHeader (struct with char bfTy[2], int bfSize, short bfReserved1, short bfReserved2, int bfOffBit) and BMPInfoHeader (struct with int biSize, int biWidth, int biHeight, short biPlanes, short biBitCount, int biCompression, int biSizeImage, int biX, int biY, int biClrUsed, int biClrImportant) for each file. Check if the file is a valid BMP (bfTy[0] == 'B' and bfTy[1] == 'M'). If not, close the file and return 0.0.
3. For each BMP, compute actual width (aw) as ((biWidth + 3)/4)*4. If biBitCount == 8, skip the color table by seeking 256*4 bytes. Read pixel data into a dynamically allocated unsigned char array of size aw * abs(biHeight).
4. Check if the two BMPs have the same biWidth and abs(biHeight). If not, free pixel arrays and return 0.0.
5. Calculate weighted MSE:
   a. Compute center_r = abs(biHeight)/2.0, center_c = biWidth/2.0, sigma = min(abs(biHeight), biWidth)/4.0.
   b. Iterate over each pixel (i,j):
      i. Get val1 = pixels1[(abs(biHeight)-1 - i)*aw1 + j], val2 = pixels2[(abs(biHeight)-1 - i)*aw2 + j].
      ii. Compute diff = val1 - val2, dist_sq = (i - center_r)^2 + (j - center_c)^2.
      iii. Compute weight = exp(-dist_sq/(2*sigma*sigma)).
      iv. Accumulate mse += weight*diff*diff, weight_sum += weight.
   c. If weight_sum > 1e-10, mse = mse / weight_sum; else mse = 0.0.
6. Free pixel arrays and return mse.

Note: Use necessary headers like <fstream>, <vector>, <cmath>, <algorithm>, etc. Handle file operations properly. Assume all used functions are already defined.
function_header: double problem_12_1(const string& file1, const string& file2)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.1" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string file1_1 = "1.bmp";
    string file2_1 = "1.bmp";

    double result1 = problem_12_1(file1_1, file2_1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 0.000000;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string file1_2 = "a.bmp";
    string file2_2 = "a.bmp";

    double result2 = problem_12_1(file1_2, file2_2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 0.000000;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string file1_3 = "b.bmp";
    string file2_3 = "b.bmp";

    double result3 = problem_12_1(file1_3, file2_3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 0.000000;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 2
step_description_prompt: Please write a C++ function named problem_12_2 that takes two const string references (file1, file2) as parameters and returns a double value, which computes the weighted Peak Signal-to-Noise Ratio (PSNR) of two BMP images using Gaussian spatial weighting. The function definition is double problem_12_2(const string& file1, const string& file2). The algorithm flow is as follows: 1. For each input filename, search for the valid path in the order of "test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, and the filename itself. Use ifstream to check if the file exists. 2. Open the two BMP files in binary mode. Read BMPFileHeader (with #pragma pack(push, 2) and #pragma pack(pop)) and BMPInfoHeader. Verify if the file is BMP by checking "BM" in bfty[0] and bfty[1]. 3. For BMPs with 8 bits per pixel, skip the color palette by seeking 256 * 4 bytes from the current position. 4. Calculate aligned width (aw) as ((width + 3) / 4) * 4 (width is biwidth, height is absolute biheight), then read pixel data into unsigned char arrays (size: aw * height). 5. Check if the two images have the same width and height. If not, return 100.0. 6. Compute weighted MSE: center is (height/2.0, width/2.0), sigma is max(width, height)/4.0. For each pixel (i,j), compute dist_sq = (i - center_i)^2 + (j - center_j)^2, weight = exp(-dist_sq/(2.0*sigma*sigma)). Sum weighted squared differences (val1-val2)^2*weight (val1 = pixels1[(height1-1-i)*aw1+j], val2 = pixels2[(height2-1-i)*aw2+j]) and weight_sum. MSE = sum_weighted_diff / (weight_sum > 1e-10 ? weight_sum : 1.0). 7. Compute PSNR as 20.0*log10(255.0/sqrt(mse)) if mse > 1e-10, else return 100.0. Handle errors (invalid paths, failed file opening, non-BMP files) by returning 100.0. Make sure to read BMP files in binary mode, handle row alignment (aw), skip color palettes for 8-bit BMPs, and use Gaussian weights for MSE calculation.
function_header: double problem_12_2(const string& file1, const string& file2)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.2" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string file1_1 = "1.bmp";
    string file2_1 = "1.bmp";

    double result1 = problem_12_2(file1_1, file2_1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 100.000000;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string file1_2 = "a.bmp";
    string file2_2 = "a.bmp";

    double result2 = problem_12_2(file1_2, file2_2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 100.000000;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string file1_3 = "b.bmp";
    string file2_3 = "b.bmp";

    double result3 = problem_12_2(file1_3, file2_3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 100.000000;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 3
step_description_prompt: Please write a C++ function named problem_12_3 that takes two const std::string& parameters (file1, file2) and returns a double, which calculates the Gaussian-weighted Structural Similarity Index (SSIM) between two BMP images.

Function definition: double problem_12_3(const std::string& file1, const std::string& file2);

Algorithm flow: 1. Find valid paths for both BMP files by checking the following patterns in order: "test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, filename. Use std::ifstream to verify if the file can be opened. 2. If either path is invalid, return 0.0. 3. Open the BMP files in binary mode, read BMPFileHeader and BMPInfoHeader structures (with #pragma pack(push, 2) and #pragma pack(pop) to ensure 2-byte alignment). Validate the BMP signature by checking if bfty[0] == 'B' and bfty[1] == 'M'; if not, close the file and return 0.0. 4. Get image width (biwidth) and height (absolute value of biheight), then compute aligned width as ((width + 3) / 4) * 4. 5. If the BMP has 8 bits per pixel (bibitcount == 8), skip the color palette by calling seekg(256 * 4, std::ios::cur). 6. Read pixel data into dynamically allocated unsigned char arrays (size: aligned width * height). 7. If the two images have different dimensions, free memory and return 0.0. 8. Compute Gaussian weights (sigma = max(width, height)/4) based on pixel distance from the center, then calculate weighted mean1, mean2, and total weight sum. 9. Use the same weights to compute weighted variance (var1, var2) and covariance (cov). 10. Free pixel memory. 11. Calculate SSIM with constants c1=0.01 and c2=0.03 using the formula: ((2 * mean1 * mean2 + c1) * (2 * cov + c2)) / ((mean1*mean1 + mean2*mean2 + c1) * (var1 + var2 + c2)), then return the result.

Note: Use std::ifstream for binary file reading, check file opening status, and handle memory deallocation for pixel arrays with delete[]. Assume helper functions (if any) are pre-defined.
function_header: double problem_12_3(const string& file1, const string& file2)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.3" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string file1_1 = "1.bmp";
    string file2_1 = "a.bmp";

    double result1 = problem_12_3(file1_1, file2_1);
    if (result1 < 0) {
    } else {
        double correct1 = 0.124691;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string file1_2 = "a.bmp";
    string file2_2 = "b.bmp";

    double result2 = problem_12_3(file1_2, file2_2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 0.126556;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string file1_3 = "b.bmp";
    string file2_3 = "1.bmp";

    double result3 = problem_12_3(file1_3, file2_3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 0.998975;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 4
step_description_prompt: Please write a C++ function named problem_12_4 that takes a const string& filename as input and returns a double. It computes the Gaussian-weighted standard deviation of pixel values in a BMP image, with the Gaussian center at the image center and sigma equal to 1/4 of the maximum of the image's width and height.
The function signature is double problem_12_4(const string& filename).
Define BMPFileHeader and BMPInfoHeader structs with #pragma pack(push, 2) before and #pragma pack(pop) after. BMPFileHeader has char bfty[2], int bfsize, short bfreserved1, short bfreserved2, int bfoffbit. BMPInfoHeader has int bisize, int biwidth, int biheight, short biplanes, short bibitcount, int bicompression, int bisizeimage, int bix, int biy, int biclrused, int biclrimportant.
Check file existence in paths {"test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, filename}; use the first existing path as filepath. If no path is found, output "Error: Cannot find data file" to cerr and return -1.0.
Open filepath in binary mode. Read BMPFileHeader and BMPInfoHeader. Check if bfty[0] is 'B' and bfty[1] is 'M'; if not, close the file and return 0.0. Calculate width as biwidth, height as abs(biheight). Compute aligned width aw as ((width + 3)/4)*4. If bibitcount is 8, skip 256*4 bytes via seekg. Allocate unsigned char* pixels = new unsigned char[aw*height]; read aw*height bytes into pixels. Close the file.
Compute center_i = height/2.0, center_j = width/2.0, sigma = max(width, height)/4.0. Initialize weighted_sum and weight_sum to 0.0. Loop i from 0 to height-1, j from 0 to width-1: dist_sq = (i-center_i)*(i-center_i)+(j-center_j)*(j-center_j); weight = exp(-dist_sq/(2*sigma*sigma)); weighted_sum += pixels[(height-1-i)*aw+j]*weight; weight_sum += weight. Mean = weight_sum>1e-10 ? weighted_sum/weight_sum : 0.0. Variance = 0.0. Loop again over i and j: recalculate weight; diff = pixels[(height-1-i)*aw+j]-mean; variance += weight*diff*diff. Variance /= weight_sum>1e-10 ? weight_sum :1.0. Delete[] pixels. Return sqrt(variance).
function_header: double problem_12_4(const string& filename)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.4" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string x1 = "1.bmp";

    double result1 = problem_12_4(x1);
 
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 64.330639;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string x2 = "a.bmp";

    double result2 = problem_12_4(x2);
    cerr << "RESULT2: " << fixed << setprecision(10) << result2 << endl;
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 48.128743;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string x3 = "b.bmp";

    double result3 = problem_12_4(x3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 63.586971;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 5
step_description_prompt: Write a C++ function named problem_12_5 that takes a const string& filename as input and returns a double, which calculates the spatially weighted entropy of a BMP image. The function includes two packed structs: BMPFileHeader (with members char bfty[2], int bfsize, short bfreserved1, short bfreserved2, int bfoffbit) and BMPInfoHeader (with members int bisize, int biwidth, int biheight, short biplanes, short bibitcount, int bicompression, int bisizeimage, int bix, int biy, int biclrused, int biclrimportant) using #pragma pack(push, 2) and #pragma pack(pop). It uses a vector<string> paths containing "test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, filename to search for the BMP file.

Algorithm steps: 1. Try opening the file from paths in order; if none exist, output "Error: Cannot find data file" and return -1.0. 2. Read BMPFileHeader and BMPInfoHeader; validate BMP format by checking if bfty[0] is 'B' and bfty[1] is 'M'. 3. Calculate aligned width aw as ((ih.biwidth + 3) / 4) * 4, height as abs(ih.biheight); if ih.bibitcount is 8, skip 256 * 4 bytes (palette). 4. Read pixel data into a dynamically allocated unsigned char array of size aw * height. 5. Compute spatially weighted histogram: center at (height / 2.0, ih.biwidth / 2.0), sigma as max(ih.biwidth, height) / 4.0; for each pixel (i, j), calculate weight as exp(-((i - center_i) * (i - center_i) + (j - center_j) * (j - center_j)) / (2 * sigma * sigma)), accumulate hist[v] by (int)(weight * 100 + 0.5) and total_weight by weight * 100. 6. Calculate entropy: for each non-zero hist[i], compute prob = hist[i] / total_weight, add -prob * log2(prob + 1e-10) to entropy (1e-10 for numerical stability). 7. Delete the pixel array and return entropy.
function_header: double problem_12_5(const string& filename)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.5" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string x1 = "1.bmp";

    double result1 = problem_12_5(x1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 5.671529;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string x2 = "a.bmp";

    double result2 = problem_12_5(x2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 1.419529;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string x3 = "b.bmp";

    double result3 = problem_12_5(x3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 5.797749;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 6
step_description_prompt: Please write a C++ function named problem_12_6 that takes an integer band_num as input and returns a double value. This function calculates a metric (20*log10(mean/noise)) where mean is the Gaussian-weighted mean of a specified band from a binary file and noise is the square root of the Gaussian-weighted variance.
Function definition: double problem_12_6(int band_num);
Algorithm flow: First, search for the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}. If not found, output "Error: Cannot find data file AA" to cerr and return -1.0. Then, read the band_num-th band (each band is 600x600 unsigned char) from the file: skip (band_num-1)*600*600 bytes, read 600 rows of 600 bytes each, and store row i as rows-1-i (reverse row order). Next, compute Gaussian-weighted mean: use center (300.0, 300.0), sigma = max(600,600)/4.0. For each pixel (i,j), calculate weight = exp(-((i-center_i)^2 + (j-center_j)^2)/(2*sigma*sigma)), sum weighted_sum (v*weight) and weight_sum (weight). Mean = weighted_sum / (weight_sum >1e-10 ? weight_sum : 0.0). Then compute Gaussian-weighted variance: sum weight*(v-mean)^2, divide by (weight_sum >1e-10 ? weight_sum : 1.0). Noise = sqrt(variance). If noise <1e-10, return 100.0. Otherwise, return 20.0*log10(mean/noise).
Note: Read the binary file with ifstream in ios::binary mode. Functions like exp, log10, sqrt are pre-defined.
function_header: double problem_12_6(int band_num)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.6" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int band1 = 1;

    double result1 = problem_12_6(band1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 21.762875;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int band2 = 3;

    double result2 = problem_12_6(band2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 12.878908;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int band3 = 5;

    double result3 = problem_12_6(band3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 8.347149;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 7
step_description_prompt: Please use C++ code to create a function named problem_12_7 that takes a const string& filename as input and returns a double. This function calculates a weighted score combining contrast (standard deviation) and entropy of a BMP image, with spatial weighting based on distance from the image center.
Function definition: double problem_12_7(const string& filename);
Algorithm flow: 1. Search for the BMP file in paths: "test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, filename. If no file exists, output "Error: Cannot find data file" to cerr and return -1.0. 2. Open the file in binary mode, read BMPFileHeader and BMPInfoHeader using #pragma pack(push,2) and #pragma pack(pop) for struct alignment. Verify BMP magic number (fh.bfty[0] == 'B' and fh.bfty[1] == 'M'). 3. Calculate width = ih.biwidth, height = abs(ih.biheight), aligned width aw = ((width + 3) / 4) * 4. 4. If ih.bibitcount == 8, skip 256 * 4 bytes to bypass the color palette. 5. Dynamically allocate an unsigned char array of size aw * height to store pixels, read pixel data (note BMP rows are stored bottom-to-top, so access via (height - 1 - i) * aw + j). 6. Compute spatial weights using a Gaussian function: sigma = max(width, height) / 4.0; for each (i,j), dist_sq = (i - center_i)^2 + (j - center_j)^2 (center_i = height / 2.0, center_j = width / 2.0), weight = exp(-dist_sq / (2.0 * sigma * sigma)). 7. Calculate weighted contrast: compute weighted sum of pixels and total weight to get mean; compute weighted variance (sum of weight*(pixel - mean)^2 / total weight), contrast = sqrt(variance). 8. Calculate weighted entropy: build a 256-bin histogram with each bin incremented by (int)(weight * 100 + 0.5); compute total_weight (sum of weight * 100); entropy = -sum(prob * log2(prob + 1e-10)) where prob = bin_count / total_weight (only for bins with count > 0). 9. Normalize contrast by 73.0 and entropy by 8.0; compute score as 0.4 * normalized_contrast + 0.6 * normalized_entropy. 10. Free the pixel array and return the score.
Ensure to handle BMP file reading correctly: check multiple paths, open in binary mode, use #pragma pack for header structs, skip color palette for 8-bit BMPs, and read pixels in bottom-to-top order.
function_header: double problem_12_7(const string& filename)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.7" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string x1 = "1.bmp";

    double result1 = problem_12_7(x1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 0.777861;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string x2 = "a.bmp";

    double result2 = problem_12_7(x2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 0.370184;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string x3 = "b.bmp";

    double result3 = problem_12_7(x3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 0.783253;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 8
step_description_prompt: Please use C++ code to generate a function named problem_12_8 that takes two int parameters band1 and band2 and returns a double. The function computes the absolute difference between the Gaussian-weighted standard deviations of two specified bands from a binary data file.

Function definition: double problem_12_8(int band1, int band2);

Algorithm steps: 1. Find the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}. If not found, output "Error: Cannot find data file AA" to cerr and return -1.0. 2. Read the specified bands (band1, band2) from the file: each band is 600x600, skip (band-1)*600*600 bytes to access the band data, read each row into a buffer, then store in a 2D vector with rows flipped (using rows-1-i). 3. Compute Gaussian weights for each pixel based on distance from the center (center_i = 300.0, center_j = 300.0; sigma = max(600,600)/4.0; weight = exp(-( (i-center_i)^2 + (j-center_j)^2 )/(2*sigma*sigma))). 4. Calculate weighted means for both bands using the weights. 5. Calculate weighted variances for both bands using the means. 6. Compute standard deviations from variances, return the absolute difference of the two standard deviations.

Note: Use ios::binary for file reading. Assume functions like ifstream, vector, exp, sqrt, abs are pre-defined.
function_header: double problem_12_8(int band1, int band2)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.8" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    int band1_1 = 1, band2_1 = 2;

    double result1 = problem_12_8(band1_1, band2_1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 1.506178;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    int band1_2 = 2, band2_2 = 3;

    double result2 = problem_12_8(band1_2, band2_2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 4.546219;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    int band1_3 = 3, band2_3 = 4;

    double result3 = problem_12_8(band1_3, band2_3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 1.602565;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 9
step_description_prompt: Please write a C++ function named problem_12_9 that takes a const string& filename as input and returns a double. This function calculates a comprehensive score for a BMP image based on weighted PSNR, SSIM, contrast, and entropy metrics.
The function signature is double problem_12_9(const string& filename);
Algorithm steps:
1. Define packed structs BMPFileHeader (with char bfty[2], int bfsize, short bfreserved1, short bfreserved2, int bfoffbit) and BMPInfoHeader (with int bisize, int biwidth, int biheight, short biplanes, short bibitcount, int bicompression, int bisizeimage, int bix, int biy, int biclrused, int biclrimportant) using #pragma pack(push,2) and #pragma pack(pop).
2. Search for the BMP file in paths: "test_data/" + filename, "../test_data/" + filename, "../../test_data/" + filename, "substep/test_data/" + filename, filename. Check file existence with ifstream. If no valid path is found, output "Error: Cannot find data file" to cerr and return -1.0.
3. Open the valid file in binary mode. Read BMPFileHeader and BMPInfoHeader. Check if bfty[0] == 'B' and bfty[1] == 'M'. If not, close the file and return 0.0.
4. Compute width (ih.biwidth), height (abs(ih.biheight)), aligned width aw ((width + 3)/4 * 4). If ih.bibitcount == 8, skip 256*4 bytes with seekg. Allocate unsigned char* pixels (size aw*height), read pixel data (pixel at (i,j) is pixels[(height-1-i)*aw + j]). Close the file.
5. Calculate metrics:
   a. Weighted MSE: Use center (height/2.0, width/2.0) and sigma (max(width,height)/4.0). Sum weighted (val-val)^2 (0) and weight_sum (exp(-( (i-center_i)^2 + (j-center_j)^2 )/(2*sigma^2))). MSE = sum / (weight_sum >1e-10 ? weight_sum : 1.0).
   b. PSNR: 100.0 if MSE <1e-10 else 20*log10(255.0/sqrt(MSE)).
   c. Weighted SSIM: Compute weighted mean (sum val*weight / weight_sum), then weighted variance (sum (val-mean)^2*weight / weight_sum) and covariance (same as variance). Use c1=0.01, c2=0.03. SSIM = ((2*mean² +c1)*(2*cov +c2)) / ((mean²+mean² +c1)*(var+var +c2)).
   d. Contrast: sqrt(var).
   e. Weighted entropy: Create 256-bin hist. Add (int)(weight*100+0.5) to hist[val], sum total_weight (weight*100). Entropy = -sum(prob*log2(prob+1e-10)) where prob=hist[i]/total_weight.
6. Normalize: normalized_psnr=psnr/100.0, normalized_ssim=ssim, normalized_contrast=contrast/73.0, normalized_entropy=entropy/8.0.
7. Score: 0.2*normalized_psnr +0.3*normalized_ssim +0.2*normalized_contrast +0.3*normalized_entropy.
8. Delete pixels. Return score.
Note: Handle file reading in binary mode. Assume other functions are defined.
function_header: double problem_12_9(const string& filename)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 12.9" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    string x1 = "1.bmp";

    double result1 = problem_12_9(x1);
    if (result1 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct1 = 0.888931;  // Expected value (updated from actual result)
        if (abs(result1 - correct1) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 2
    string x2 = "a.bmp";

    double result2 = problem_12_9(x2);
    if (result2 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct2 = 0.685092;  // Expected value (updated from actual result)
        if (abs(result2 - correct2) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }
// Test 3
    string x3 = "b.bmp";

    double result3 = problem_12_9(x3);
    if (result3 < 0) {
        cout << "Wrong (File not found)" << endl;
    } else {
        double correct3 = 0.891626;  // Expected value (updated from actual result)
        if (abs(result3 - correct3) < tolerance) {
            cout << "Correct" << endl;
            correct_count++;
        } else {
            cout << "Wrong" << endl;
        }
    }

    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

General solution:

General tests: