Download third_party/ktx-src/external/astc-encoder/Source/astcenccli_error_metrics.cpp from kimjunhan/vkgs-sim: direct link, hf CLI and curl.
- Browser
- Download file 11.4 kB
-
https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/third_party/ktx-src/external/astc-encoder/Source/astcenccli_error_metrics.cpp
- Command line
-
hf download hf://kimjunhan/vkgs-sim/third_party/ktx-src/external/astc-encoder/Source/astcenccli_error_metrics.cpp
-
curl -L -o astcenccli_error_metrics.cpp https://huggingface.co/kimjunhan/vkgs-sim/resolve/main/third_party/ktx-src/external/astc-encoder/Source/astcenccli_error_metrics.cpp
11.4 kB
| // SPDX-License-Identifier: Apache-2.0 | |
| // ---------------------------------------------------------------------------- | |
| // Copyright 2011-2022 Arm Limited | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not | |
| // use this file except in compliance with the License. You may obtain a copy | |
| // of the License at: | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
| // License for the specific language governing permissions and limitations | |
| // under the License. | |
| // ---------------------------------------------------------------------------- | |
| /** | |
| * @brief Functions for computing image error metrics. | |
| */ | |
| /** | |
| * @brief An accumulator for errors. | |
| */ | |
| class error_accum4 | |
| { | |
| public: | |
| /** @brief The running sum. */ | |
| double sum_r { 0.0 }; | |
| double sum_g { 0.0 }; | |
| double sum_b { 0.0 }; | |
| double sum_a { 0.0 }; | |
| }; | |
| /** | |
| * @brief Incremental addition operator for error accumulators. | |
| * | |
| * @param val The accumulator to increment | |
| * @param inc The increment to apply | |
| * | |
| * @return The updated accumulator | |
| */ | |
| static error_accum4& operator+=( | |
| error_accum4 &val, | |
| vfloat4 inc | |
| ) { | |
| val.sum_r += static_cast<double>(inc.lane<0>()); | |
| val.sum_g += static_cast<double>(inc.lane<1>()); | |
| val.sum_b += static_cast<double>(inc.lane<2>()); | |
| val.sum_a += static_cast<double>(inc.lane<3>()); | |
| return val; | |
| } | |
| /** | |
| * @brief mPSNR tone-mapping operator for HDR images. | |
| * | |
| * @param val The color value to tone map | |
| * @param fstop The exposure fstop; should be in range [-125, 125] | |
| * | |
| * @return The mapped color value in [0.0f, 255.0f] range | |
| */ | |
| static float mpsnr_operator( | |
| float val, | |
| int fstop | |
| ) { | |
| if32 p; | |
| p.u = 0x3f800000 + (fstop << 23); // 0x3f800000 is 1.0f | |
| val *= p.f; | |
| val = powf(val, (1.0f / 2.2f)); | |
| val *= 255.0f; | |
| return astc::clamp(val, 0.0f, 255.0f); | |
| } | |
| /** | |
| * @brief mPSNR difference between two values. | |
| * | |
| * Differences are given as "val1 - val2". | |
| * | |
| * @param val1 The first color value | |
| * @param val2 The second color value | |
| * @param fstop_lo The low exposure fstop; should be in range [-125, 125] | |
| * @param fstop_hi The high exposure fstop; should be in range [-125, 125] | |
| * | |
| * @return The summed mPSNR difference across all active fstop levels | |
| */ | |
| static float mpsnr_sumdiff( | |
| float val1, | |
| float val2, | |
| int fstop_lo, | |
| int fstop_hi | |
| ) { | |
| float summa = 0.0f; | |
| for (int i = fstop_lo; i <= fstop_hi; i++) | |
| { | |
| float mval1 = mpsnr_operator(val1, i); | |
| float mval2 = mpsnr_operator(val2, i); | |
| float mdiff = mval1 - mval2; | |
| summa += mdiff * mdiff; | |
| } | |
| return summa; | |
| } | |
| /* See header for documentation */ | |
| void compute_error_metrics( | |
| bool compute_hdr_metrics, | |
| bool compute_normal_metrics, | |
| int input_components, | |
| const astcenc_image* img1, | |
| const astcenc_image* img2, | |
| int fstop_lo, | |
| int fstop_hi | |
| ) { | |
| static const int componentmasks[5] { 0x00, 0x07, 0x0C, 0x07, 0x0F }; | |
| int componentmask = componentmasks[input_components]; | |
| error_accum4 errorsum; | |
| error_accum4 alpha_scaled_errorsum; | |
| error_accum4 log_errorsum; | |
| error_accum4 mpsnr_errorsum; | |
| double mean_angular_errorsum = 0.0; | |
| double worst_angular_errorsum = 0.0; | |
| unsigned int dim_x = astc::min(img1->dim_x, img2->dim_x); | |
| unsigned int dim_y = astc::min(img1->dim_y, img2->dim_y); | |
| unsigned int dim_z = astc::min(img1->dim_z, img2->dim_z); | |
| if (img1->dim_x != img2->dim_x || | |
| img1->dim_y != img2->dim_y || | |
| img1->dim_z != img2->dim_z) | |
| { | |
| printf("WARNING: Only intersection of images will be compared:\n" | |
| " Image 1: %dx%dx%d\n" | |
| " Image 2: %dx%dx%d\n", | |
| img1->dim_x, img1->dim_y, img1->dim_z, | |
| img2->dim_x, img2->dim_y, img2->dim_z); | |
| } | |
| double rgb_peak = 0.0; | |
| unsigned int xsize1 = img1->dim_x; | |
| unsigned int xsize2 = img2->dim_x; | |
| for (unsigned int z = 0; z < dim_z; z++) | |
| { | |
| for (unsigned int y = 0; y < dim_y; y++) | |
| { | |
| for (unsigned int x = 0; x < dim_x; x++) | |
| { | |
| vfloat4 color1; | |
| vfloat4 color2; | |
| if (img1->data_type == ASTCENC_TYPE_U8) | |
| { | |
| uint8_t* data8 = static_cast<uint8_t*>(img1->data[z]); | |
| color1 = vfloat4( | |
| data8[(4 * xsize1 * y) + (4 * x )], | |
| data8[(4 * xsize1 * y) + (4 * x + 1)], | |
| data8[(4 * xsize1 * y) + (4 * x + 2)], | |
| data8[(4 * xsize1 * y) + (4 * x + 3)]); | |
| color1 = color1 / 255.0f; | |
| } | |
| else if (img1->data_type == ASTCENC_TYPE_F16) | |
| { | |
| uint16_t* data16 = static_cast<uint16_t*>(img1->data[z]); | |
| vint4 color1i = vint4( | |
| data16[(4 * xsize1 * y) + (4 * x )], | |
| data16[(4 * xsize1 * y) + (4 * x + 1)], | |
| data16[(4 * xsize1 * y) + (4 * x + 2)], | |
| data16[(4 * xsize1 * y) + (4 * x + 3)]); | |
| color1 = float16_to_float(color1i); | |
| color1 = clamp(0, 65504.0f, color1); | |
| } | |
| else // if (img1->data_type == ASTCENC_TYPE_F32) | |
| { | |
| assert(img1->data_type == ASTCENC_TYPE_F32); | |
| float* data32 = static_cast<float*>(img1->data[z]); | |
| color1 = vfloat4( | |
| data32[(4 * xsize1 * y) + (4 * x )], | |
| data32[(4 * xsize1 * y) + (4 * x + 1)], | |
| data32[(4 * xsize1 * y) + (4 * x + 2)], | |
| data32[(4 * xsize1 * y) + (4 * x + 3)]); | |
| color1 = clamp(0, 65504.0f, color1); | |
| } | |
| if (img2->data_type == ASTCENC_TYPE_U8) | |
| { | |
| uint8_t* data8 = static_cast<uint8_t*>(img2->data[z]); | |
| color2 = vfloat4( | |
| data8[(4 * xsize2 * y) + (4 * x )], | |
| data8[(4 * xsize2 * y) + (4 * x + 1)], | |
| data8[(4 * xsize2 * y) + (4 * x + 2)], | |
| data8[(4 * xsize2 * y) + (4 * x + 3)]); | |
| color2 = color2 / 255.0f; | |
| } | |
| else if (img2->data_type == ASTCENC_TYPE_F16) | |
| { | |
| uint16_t* data16 = static_cast<uint16_t*>(img2->data[z]); | |
| vint4 color2i = vint4( | |
| data16[(4 * xsize2 * y) + (4 * x )], | |
| data16[(4 * xsize2 * y) + (4 * x + 1)], | |
| data16[(4 * xsize2 * y) + (4 * x + 2)], | |
| data16[(4 * xsize2 * y) + (4 * x + 3)]); | |
| color2 = float16_to_float(color2i); | |
| color2 = clamp(0, 65504.0f, color2); | |
| } | |
| else // if (img2->data_type == ASTCENC_TYPE_F32) | |
| { | |
| assert(img2->data_type == ASTCENC_TYPE_F32); | |
| float* data32 = static_cast<float*>(img2->data[z]); | |
| color2 = vfloat4( | |
| data32[(4 * xsize2 * y) + (4 * x )], | |
| data32[(4 * xsize2 * y) + (4 * x + 1)], | |
| data32[(4 * xsize2 * y) + (4 * x + 2)], | |
| data32[(4 * xsize2 * y) + (4 * x + 3)]); | |
| color2 = clamp(0, 65504.0f, color2); | |
| } | |
| rgb_peak = astc::max(static_cast<double>(color1.lane<0>()), | |
| static_cast<double>(color1.lane<1>()), | |
| static_cast<double>(color1.lane<2>()), | |
| rgb_peak); | |
| vfloat4 diffcolor = color1 - color2; | |
| vfloat4 diffcolor_sq = diffcolor * diffcolor; | |
| errorsum += diffcolor_sq; | |
| vfloat4 alpha_scaled_diffcolor = vfloat4( | |
| diffcolor.lane<0>() * color1.lane<3>(), | |
| diffcolor.lane<1>() * color1.lane<3>(), | |
| diffcolor.lane<2>() * color1.lane<3>(), | |
| diffcolor.lane<3>()); | |
| vfloat4 alpha_scaled_diffcolor_sq = alpha_scaled_diffcolor * alpha_scaled_diffcolor; | |
| alpha_scaled_errorsum += alpha_scaled_diffcolor_sq; | |
| if (compute_hdr_metrics) | |
| { | |
| vfloat4 log_input_color1 = log2(color1); | |
| vfloat4 log_input_color2 = log2(color2); | |
| vfloat4 log_diffcolor = log_input_color1 - log_input_color2; | |
| log_errorsum += log_diffcolor * log_diffcolor; | |
| vfloat4 mpsnr_error = vfloat4( | |
| mpsnr_sumdiff(color1.lane<0>(), color2.lane<0>(), fstop_lo, fstop_hi), | |
| mpsnr_sumdiff(color1.lane<1>(), color2.lane<1>(), fstop_lo, fstop_hi), | |
| mpsnr_sumdiff(color1.lane<2>(), color2.lane<2>(), fstop_lo, fstop_hi), | |
| mpsnr_sumdiff(color1.lane<3>(), color2.lane<3>(), fstop_lo, fstop_hi)); | |
| mpsnr_errorsum += mpsnr_error; | |
| } | |
| if (compute_normal_metrics) | |
| { | |
| // Decode the normal vector | |
| vfloat4 normal1 = (color1 - 0.5f) * 2.0f; | |
| normal1 = normalize_safe(normal1.swz<0, 1, 2>(), unit3()); | |
| vfloat4 normal2 = (color2 - 0.5f) * 2.0f; | |
| normal2 = normalize_safe(normal2.swz<0, 1, 2>(), unit3()); | |
| // Float error can push this outside of valid range for acos, so clamp to avoid NaN issues | |
| float normal_cos = clamp(-1.0f, 1.0f, dot3(normal1, normal2)).lane<0>(); | |
| float rad_to_degrees = 180.0f / astc::PI; | |
| double error_degrees = std::acos(static_cast<double>(normal_cos)) * static_cast<double>(rad_to_degrees); | |
| mean_angular_errorsum += error_degrees / (dim_x * dim_y * dim_z); | |
| worst_angular_errorsum = astc::max(worst_angular_errorsum, error_degrees); | |
| } | |
| } | |
| } | |
| } | |
| double pixels = static_cast<double>(dim_x * dim_y * dim_z); | |
| double samples = 0.0; | |
| double num = 0.0; | |
| double alpha_num = 0.0; | |
| double log_num = 0.0; | |
| double mpsnr_num = 0.0; | |
| if (componentmask & 1) | |
| { | |
| num += errorsum.sum_r; | |
| alpha_num += alpha_scaled_errorsum.sum_r; | |
| log_num += log_errorsum.sum_r; | |
| mpsnr_num += mpsnr_errorsum.sum_r; | |
| samples += pixels; | |
| } | |
| if (componentmask & 2) | |
| { | |
| num += errorsum.sum_g; | |
| alpha_num += alpha_scaled_errorsum.sum_g; | |
| log_num += log_errorsum.sum_g; | |
| mpsnr_num += mpsnr_errorsum.sum_g; | |
| samples += pixels; | |
| } | |
| if (componentmask & 4) | |
| { | |
| num += errorsum.sum_b; | |
| alpha_num += alpha_scaled_errorsum.sum_b; | |
| log_num += log_errorsum.sum_b; | |
| mpsnr_num += mpsnr_errorsum.sum_b; | |
| samples += pixels; | |
| } | |
| if (componentmask & 8) | |
| { | |
| num += errorsum.sum_a; | |
| alpha_num += alpha_scaled_errorsum.sum_a; | |
| samples += pixels; | |
| } | |
| double denom = samples; | |
| double stopcount = static_cast<double>(fstop_hi - fstop_lo + 1); | |
| double mpsnr_denom = pixels * 3.0 * stopcount * 255.0 * 255.0; | |
| double psnr; | |
| if (num == 0.0) | |
| { | |
| psnr = 999.0; | |
| } | |
| else | |
| { | |
| psnr = 10.0 * log10(denom / num); | |
| } | |
| double rgb_psnr = psnr; | |
| printf("Quality metrics\n"); | |
| printf("===============\n\n"); | |
| if (componentmask & 8) | |
| { | |
| printf(" PSNR (LDR-RGBA): %9.4f dB\n", psnr); | |
| double alpha_psnr; | |
| if (alpha_num == 0.0) | |
| { | |
| alpha_psnr = 999.0; | |
| } | |
| else | |
| { | |
| alpha_psnr = 10.0 * log10(denom / alpha_num); | |
| } | |
| printf(" Alpha-weighted PSNR: %9.4f dB\n", alpha_psnr); | |
| double rgb_num = errorsum.sum_r + errorsum.sum_g + errorsum.sum_b; | |
| if (rgb_num == 0.0) | |
| { | |
| rgb_psnr = 999.0; | |
| } | |
| else | |
| { | |
| rgb_psnr = 10.0 * log10(pixels * 3.0 / rgb_num); | |
| } | |
| printf(" PSNR (LDR-RGB): %9.4f dB\n", rgb_psnr); | |
| } | |
| else | |
| { | |
| printf(" PSNR (LDR-RGB): %9.4f dB\n", psnr); | |
| } | |
| if (compute_hdr_metrics) | |
| { | |
| printf(" PSNR (RGB norm to peak): %9.4f dB (peak %f)\n", | |
| rgb_psnr + 20.0 * log10(rgb_peak), rgb_peak); | |
| double mpsnr; | |
| if (mpsnr_num == 0.0) | |
| { | |
| mpsnr = 999.0; | |
| } | |
| else | |
| { | |
| mpsnr = 10.0 * log10(mpsnr_denom / mpsnr_num); | |
| } | |
| printf(" mPSNR (RGB): %9.4f dB (fstops %+d to %+d)\n", | |
| mpsnr, fstop_lo, fstop_hi); | |
| double logrmse = sqrt(log_num / pixels); | |
| printf(" LogRMSE (RGB): %9.4f\n", logrmse); | |
| } | |
| if (compute_normal_metrics) | |
| { | |
| printf(" Mean Angular Error: %9.4f degrees\n", mean_angular_errorsum); | |
| printf(" Worst Angular Error: %9.4f degrees\n", worst_angular_errorsum); | |
| } | |
| printf("\n"); | |
| } | |