### Command-Line Tool Usage Source: https://context7.com/google/butteraugli/llms.txt Instructions for building and using the butteraugli command-line tool for image comparison and heatmap generation. ```APIDOC ## Command-Line Tool Usage ### Description The butteraugli binary compares two images and outputs a perceptual difference score. Optionally generates a visual heatmap showing where differences occur. ### Method Command-Line Execution ### Endpoint N/A (Executable) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```bash # Build with Bazel bazel build -c opt //:butteraugli # Or build with Make (requires libpng and libjpeg) cd butteraugli && make # Basic comparison - outputs a single floating point score ./butteraugli original.png compressed.jpg # Output: 1.234567 # Generate heatmap visualization ./butteraugli original.png compressed.jpg heatmap.ppm # Interpreting scores: # < 1.0 : Images appear nearly identical (excellent quality) # 1.0-2.0: Subtle differences may be noticeable (good quality) # > 2.0 : Differences are clearly visible (poor quality) ``` ### Response #### Success Response (200) - **Output Score**: A single floating-point number representing the perceptual difference between the two images. - **Heatmap Image**: A `.ppm` file visualizing the perceptual differences across the image. #### Response Example ``` 1.234567 ``` ``` -------------------------------- ### Compare JPEG Quality via Command Line Source: https://context7.com/google/butteraugli/llms.txt Use the butteraugli binary to compare a source image against compressed versions at different quality levels. ```bash ./butteraugli photo.png photo_q95.jpg # Output: ~0.8 (excellent) ./butteraugli photo.png photo_q85.jpg # Output: ~1.5 (good) ./butteraugli photo.png photo_q70.jpg # Output: ~3.0 (noticeable artifacts) ``` -------------------------------- ### Compare Images with Butteraugli CLI Source: https://github.com/google/butteraugli/blob/master/README.md Use the command-line utility to compare two image files. Supports PNG and JPG inputs. ```bash butteraugli image1.{png|jpg} image2.{png|jpg} ``` -------------------------------- ### Butteraugli Command-Line Tool Usage Source: https://context7.com/google/butteraugli/llms.txt The butteraugli binary compares two images and outputs a perceptual difference score. It can also optionally generate a visual heatmap of the differences. Scores below 1.0 indicate near-identical images, 1.0-2.0 suggest subtle differences, and above 2.0 indicate clearly visible differences. ```bash # Build with Bazel bazel build -c opt //:butteraugli # Or build with Make (requires libpng and libjpeg) cd butteraugli && make # Basic comparison - outputs a single floating point score ./butteraugli original.png compressed.jpg # Output: 1.234567 # Generate heatmap visualization ./butteraugli original.png compressed.jpg heatmap.ppm # Interpreting scores: # < 1.0 : Images appear nearly identical (excellent quality) # 1.0-2.0: Subtle differences may be noticeable (good quality) # > 2.0 : Differences are clearly visible (poor quality) ``` -------------------------------- ### Perform Color Space Conversion and Modeling Source: https://context7.com/google/butteraugli/llms.txt Convert linear RGB images to the XYB opponent color space and simulate photopsin absorbance for perceptual modeling. ```cpp #include "butteraugli/butteraugli.h" #include // Start with linear RGB image planes size_t xsize = 512; size_t ysize = 512; std::vector rgb = butteraugli::CreatePlanes(xsize, ysize, 3); // Fill with linear RGB values (gamma-corrected)... // Convert to opponent color space (XYB) std::vector xyb = butteraugli::OpsinDynamicsImage(rgb); // xyb[0] = X component (red-green opponent) // xyb[1] = Y component (luminance) // xyb[2] = B component (blue) // Low-level RGB to XYB conversion for individual pixels float r = 128.0f, g = 100.0f, b = 80.0f; float x, y, blue; butteraugli::RgbToXyb(r, g, b, &x, &y, &blue); // Photopsin absorbance modeling (cone response simulation) float in_r = 0.5f, in_g = 0.4f, in_b = 0.3f; float out0, out1, out2; butteraugli::OpsinAbsorbance(in_r, in_g, in_b, &out0, &out1, &out2); ``` -------------------------------- ### Generate Difference Heatmap with Butteraugli CLI Source: https://github.com/google/butteraugli/blob/master/README.md Generate a heatmap visualizing the differences between two images. The output is a PNM image. ```bash butteraugli image1.{png|jpg} image2.{png|jpg} heatmap.pnm ``` -------------------------------- ### Generate Adaptive Quantization Map Source: https://context7.com/google/butteraugli/llms.txt Generates a quantization map for adaptive compression based on image content. Low values in the map indicate areas where coarse quantization is acceptable, while high values require fine quantization. The input image should be prepared as packed vectors of linear RGB values. ```cpp #include "butteraugli/butteraugli.h" #include size_t xsize = 1024; size_t ysize = 768; // Prepare image as packed vectors (row-major, one vector per channel) std::vector> rgb(3); for (int c = 0; c < 3; c++) { rgb[c].resize(xsize * ysize); // Fill with linear RGB values... } // Output quantization map std::vector quant_map; bool success = butteraugli::ButteraugliAdaptiveQuantization(xsize, ysize, rgb, quant_map); if (success) { // quant_map values range from kButteraugliQuantLow to kButteraugliQuantHigh // Low values (~0.26): can use coarse quantization // High values (~1.45): need fine quantization for (size_t y = 0; y < ysize; y++) { for (size_t x = 0; x < xsize; x++) { float q = quant_map[y * xsize + x]; // Use q to adjust compression quality spatially // Higher q = finer quantization needed } } } ``` -------------------------------- ### CreateHeatMapImage Source: https://context7.com/google/butteraugli/llms.txt Generates an RGB heatmap visualization of the difference map between two images, highlighting areas with perceptual differences. ```APIDOC ## CreateHeatMapImage ### Description Generates an RGB heatmap visualization of the difference map. Useful for debugging and visualizing which areas of an image have perceptual differences. Colors range from black/blue (minimal difference) through green/yellow to red/pink (severe difference). ### Method C++ Function Call ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "butteraugli/butteraugli.h" #include #include // After computing diffmap from ButteraugliInterface or ButteraugliComparator butteraugli::ImageF diffmap; // Already computed size_t xsize = diffmap.xsize(); size_t ysize = diffmap.ysize(); // Define quality thresholds double good_threshold = butteraugli::ButteraugliFuzzyInverse(1.5); double bad_threshold = butteraugli::ButteraugliFuzzyInverse(0.5); // Convert ImageF to packed vector for CreateHeatMapImage std::vector distmap_packed(xsize * ysize); for (size_t y = 0; y < ysize; y++) { const float* row = diffmap.Row(y); for (size_t x = 0; x < xsize; x++) { distmap_packed[y * xsize + x] = row[x]; } } // Generate RGB heatmap std::vector heatmap; butteraugli::CreateHeatMapImage(distmap_packed, good_threshold, bad_threshold, xsize, ysize, &heatmap); // Write as PPM image file FILE* f = fopen("heatmap.ppm", "wb"); fprintf(f, "P6\n%zu %zu\n255\n", xsize, ysize); fwrite(heatmap.data(), 1, heatmap.size(), f); fclose(f); ``` ### Response #### Success Response (200) `heatmap` (std::vector): A vector containing the RGB pixel data for the heatmap image in PPM format (P6). The data can be written directly to a .ppm file. #### Response Example ``` // The 'heatmap' vector is populated with RGB data. // Example of writing to a file: // FILE* f = fopen("heatmap.ppm", "wb"); // fprintf(f, "P6\n%zu %zu\n255\n", xsize, ysize); // fwrite(heatmap.data(), 1, heatmap.size(), f); // fclose(f); ``` ``` -------------------------------- ### Create Heatmap Image from Difference Map Source: https://context7.com/google/butteraugli/llms.txt Generates an RGB heatmap visualization of a difference map, useful for debugging perceptual differences. The input difference map should be packed into a single vector. Quality thresholds can be provided to influence the color mapping. ```cpp #include "butteraugli/butteraugli.h" #include #include // After computing diffmap from ButteraugliInterface or ButteraugliComparator butteraugli::ImageF diffmap; // Already computed size_t xsize = diffmap.xsize(); size_t ysize = diffmap.ysize(); // Define quality thresholds double good_threshold = butteraugli::ButteraugliFuzzyInverse(1.5); double bad_threshold = butteraugli::ButteraugliFuzzyInverse(0.5); // Convert ImageF to packed vector for CreateHeatMapImage std::vector distmap_packed(xsize * ysize); for (size_t y = 0; y < ysize; y++) { const float* row = diffmap.Row(y); for (size_t x = 0; x < xsize; x++) { distmap_packed[y * xsize + x] = row[x]; } } // Generate RGB heatmap std::vector heatmap; butteraugli::CreateHeatMapImage(distmap_packed, good_threshold, bad_threshold, xsize, ysize, &heatmap); // Write as PPM image file FILE* f = fopen("heatmap.ppm", "wb"); fprintf(f, "P6\n%zu %zu\n255\n", xsize, ysize); fwrite(heatmap.data(), 1, heatmap.size(), f); fclose(f); ``` -------------------------------- ### Manage Cache-Aligned Images with Image Source: https://context7.com/google/butteraugli/llms.txt The Image template provides 2D storage with memory padding for SIMD operations. Supports Image8 (uint8_t) and ImageF (float) types. ```cpp #include "butteraugli/butteraugli.h" // Create a floating-point image size_t width = 800; size_t height = 600; butteraugli::ImageF image(width, height); // Access individual pixels for (size_t y = 0; y < image.ysize(); ++y) { float* row = image.Row(y); for (size_t x = 0; x < image.xsize(); ++x) { row[x] = static_cast(x + y); } } // Create image initialized to a specific value butteraugli::ImageF black_image(width, height, 0.0f); butteraugli::Image8 white_image(width, height, 255); // Create multiple image planes (e.g., RGB channels) std::vector rgb_planes = butteraugli::CreatePlanes(width, height, 3); // Copy an image butteraugli::ImageF copy = butteraugli::CopyPixels(image); // Copy multiple planes std::vector rgb_copy = butteraugli::CopyPlanes(rgb_planes); // Convert between padded images and packed vectors std::vector packed(width * height); butteraugli::CopyToPacked(image, &packed); // Image to vector butteraugli::ImageF unpacked(width, height); butteraugli::CopyFromPacked(packed, &unpacked); // Vector to image ``` -------------------------------- ### Compare Two Images with ButteraugliInterface Source: https://context7.com/google/butteraugli/llms.txt Use ButteraugliInterface to compare two RGB images in linear color space. Ensure pixel values are gamma-corrected. The returned score indicates perceptual quality, where lower values mean more similar images. ```cpp #include "butteraugli/butteraugli.h" #include // Prepare two images as linear RGB values (gamma-corrected) // Each image is a vector of 3 ImageF planes (R, G, B) // Pixel values should be in range 0-255 after gamma correction: // butteraugli_val = 255.0 * pow(png_val / 255.0, gamma) // where gamma is typically 2.2 size_t xsize = 640; size_t ysize = 480; // Create image planes for reference and distorted images std::vector rgb0 = butteraugli::CreatePlanes(xsize, ysize, 3); std::vector rgb1 = butteraugli::CreatePlanes(xsize, ysize, 3); // Fill rgb0 and rgb1 with linear color values... // (Apply gamma correction: value = 255.0 * pow(srgb_value / 255.0, 2.2)) // hf_asymmetry controls the asymmetry of high-frequency components (typically 1.0) float hf_asymmetry = 1.0f; // Output: difference map and scalar score butteraugli::ImageF diffmap; double diffvalue; bool success = butteraugli::ButteraugliInterface(rgb0, rgb1, hf_asymmetry, diffmap, diffvalue); if (success) { // Interpret the score: // diffvalue < kButteraugliGood: images appear identical // diffvalue > kButteraugliBad: noticeable difference // Between: subtle difference observable printf("Butteraugli score: %f\n", diffvalue); } ``` -------------------------------- ### ButteraugliAdaptiveQuantization Source: https://context7.com/google/butteraugli/llms.txt Generates a quantization map for adaptive compression based on image content. This map indicates how much quantization each area can tolerate without visible artifacts. ```APIDOC ## ButteraugliAdaptiveQuantization ### Description Generates a quantization map for adaptive compression based on image content. Returns values indicating how much quantization each area can tolerate without visible artifacts. Low values indicate areas where coarse quantization is acceptable (e.g., noise), high values require fine quantization (e.g., smooth gradients). ### Method C++ Function Call ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "butteraugli/butteraugli.h" #include size_t xsize = 1024; size_t ysize = 768; // Prepare image as packed vectors (row-major, one vector per channel) std::vector> rgb(3); for (int c = 0; c < 3; c++) { rgb[c].resize(xsize * ysize); // Fill with linear RGB values... } // Output quantization map std::vector quant_map; bool success = butteraugli::ButteraugliAdaptiveQuantization(xsize, ysize, rgb, quant_map); if (success) { // quant_map values range from kButteraugliQuantLow to kButteraugliQuantHigh // Low values (~0.26): can use coarse quantization // High values (~1.45): need fine quantization for (size_t y = 0; y < ysize; y++) { for (size_t x = 0; x < xsize; x++) { float q = quant_map[y * xsize + x]; // Use q to adjust compression quality spatially // Higher q = finer quantization needed } } } ``` ### Response #### Success Response (200) `quant_map` (std::vector): A vector containing quantization values for each pixel. Values range from approximately 0.26 (coarse quantization acceptable) to 1.45 (fine quantization required). #### Response Example ``` // quant_map is populated with float values representing quantization needs. // Example iteration: // float q = quant_map[y * xsize + x]; ``` ``` -------------------------------- ### Compare Multiple Images with ButteraugliComparator Source: https://context7.com/google/butteraugli/llms.txt Use ButteraugliComparator for efficient comparison of multiple distorted images against a single reference. It precomputes transforms on the reference image. Obtain scalar scores from the generated difference maps. ```cpp #include "butteraugli/butteraugli.h" #include size_t xsize = 1920; size_t ysize = 1080; // Create reference image (linear RGB) std::vector reference = butteraugli::CreatePlanes(xsize, ysize, 3); // Fill reference with linear color values... // Create comparator with reference image double hf_asymmetry = 1.0; butteraugli::ButteraugliComparator comparator(reference, hf_asymmetry); // Compare against multiple distorted versions std::vector distorted1 = butteraugli::CreatePlanes(xsize, ysize, 3); std::vector distorted2 = butteraugli::CreatePlanes(xsize, ysize, 3); // Fill distorted images... butteraugli::ImageF result1(xsize, ysize); butteraugli::ImageF result2(xsize, ysize); // Generate difference maps comparator.Diffmap(distorted1, result1); comparator.Diffmap(distorted2, result2); // Get scalar scores from difference maps double score1 = butteraugli::ButteraugliScoreFromDiffmap(result1); double score2 = butteraugli::ButteraugliScoreFromDiffmap(result2); printf("Score for variant 1: %f\n", score1); printf("Score for variant 2: %f\n", score2); ``` -------------------------------- ### Convert Raw Butteraugli Scores to Fuzzy Classes Source: https://context7.com/google/butteraugli/llms.txt Converts raw Butteraugli scores into continuous fuzzy class values. Use this for optimization algorithms that benefit from smooth gradients at quality boundaries. ButteraugliFuzzyInverse can be used to find score thresholds for specific quality levels. ```cpp #include "butteraugli/butteraugli.h" // Raw butteraugli scores from image comparison double score_perfect = 0.0; double score_good = 0.5; double score_acceptable = 1.0; double score_bad = 2.5; // Convert to fuzzy class values double class_perfect = butteraugli::ButteraugliFuzzyClass(score_perfect); double class_good = butteraugli::ButteraugliFuzzyClass(score_good); double class_acceptable = butteraugli::ButteraugliFuzzyClass(score_acceptable); double class_bad = butteraugli::ButteraugliFuzzyClass(score_bad); printf("Perfect score %f -> fuzzy class %f\n", score_perfect, class_perfect); // ~2.0 printf("Good score %f -> fuzzy class %f\n", score_good, class_good); // ~1.9 printf("Acceptable score %f -> fuzzy class %f\n", score_acceptable, class_acceptable); // ~1.0 printf("Bad score %f -> fuzzy class %f\n", score_bad, class_bad); // ~0.0 // Use ButteraugliFuzzyInverse to get thresholds for quality levels // Input: 0 (bad) to 2 (good) double good_threshold = butteraugli::ButteraugliFuzzyInverse(1.5); // Score for "good" quality double bad_threshold = butteraugli::ButteraugliFuzzyInverse(0.5); // Score for "bad" quality printf("Good quality threshold: %f\n", good_threshold); printf("Bad quality threshold: %f\n", bad_threshold); ``` -------------------------------- ### ButteraugliFuzzyClass and ButteraugliFuzzyInverse Source: https://context7.com/google/butteraugli/llms.txt Converts raw Butteraugli scores into fuzzy class values and vice-versa. Useful for mapping perceptual quality scores to continuous values for optimization algorithms. ```APIDOC ## ButteraugliFuzzyClass and ButteraugliFuzzyInverse ### Description Converts raw butteraugli scores into fuzzy class values with continuous boundaries. Returns 2.0 for perfect match, 1.0 for acceptable quality, and 0.0 for bad quality. Useful for optimization algorithms that benefit from smooth gradients at quality boundaries. ### Method C++ Function Calls ### Endpoint N/A (Library Functions) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cpp #include "butteraugli/butteraugli.h" // Raw butteraugli scores from image comparison double score_perfect = 0.0; double score_good = 0.5; double score_acceptable = 1.0; double score_bad = 2.5; // Convert to fuzzy class values double class_perfect = butteraugli::ButteraugliFuzzyClass(score_perfect); double class_good = butteraugli::ButteraugliFuzzyClass(score_good); double class_acceptable = butteraugli::ButteraugliFuzzyClass(score_acceptable); double class_bad = butteraugli::ButteraugliFuzzyClass(score_bad); printf("Perfect score %f -> fuzzy class %f\n", score_perfect, class_perfect); // ~2.0 printf("Good score %f -> fuzzy class %f\n", score_good, class_good); // ~1.9 printf("Acceptable score %f -> fuzzy class %f\n", score_acceptable, class_acceptable); // ~1.0 printf("Bad score %f -> fuzzy class %f\n", score_bad, class_bad); // ~0.0 // Use ButteraugliFuzzyInverse to get thresholds for quality levels // Input: 0 (bad) to 2 (good) double good_threshold = butteraugli::ButteraugliFuzzyInverse(1.5); // Score for "good" quality double bad_threshold = butteraugli::ButteraugliFuzzyInverse(0.5); // Score for "bad" quality printf("Good quality threshold: %f\n", good_threshold); printf("Bad quality threshold: %f\n", bad_threshold); ``` ### Response #### Success Response (200) N/A (Function returns double) #### Response Example ``` Perfect score 0.000000 -> fuzzy class 2.000000 Good score 0.500000 -> fuzzy class 1.900000 Acceptable score 1.000000 -> fuzzy class 1.000000 Bad score 2.500000 -> fuzzy class 0.000000 Good quality threshold: 1.500000 Bad quality threshold: 0.500000 ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.