From 41e6aad693d1e23dcb06a3a09dc82cf0897c2582 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Date: Tue, 9 Sep 2014 21:57:46 -0700 Subject: [PATCH] Avoid repeated adds and ensure correct round-trip result. --- stb_image_resize.h | 30 +++++++++++++++++++----------- tests/resample_test.cpp | 3 +++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/stb_image_resize.h b/stb_image_resize.h index b6dc994..4965436 100644 --- a/stb_image_resize.h +++ b/stb_image_resize.h @@ -445,7 +445,7 @@ static float stbir__srgb_uchar_to_linear_float[256] = { // sRGB transition values, scaled by 1<<28 static int stbir__srgb_offset_to_linear_scaled[256] = { - 40579, 121738, 202897, 284056, 365216, 446375, 527534, 608693, + 40579, 121738, 202897, 284056, 365216, 446375, 527534, 608693, 689852, 771011, 852421, 938035, 1028466, 1123787, 1224073, 1329393, 1439819, 1555418, 1676257, 1802402, 1933917, 2070867, 2213313, 2361317, 2514938, 2674237, 2839271, 3010099, 3186776, 3369359, 3557903, 3752463, @@ -499,16 +499,25 @@ static unsigned char stbir__linear_to_srgb_uchar(float f) { int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp int v = 0; + int i; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+128 ]) v += 128; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 64 ]) v += 64; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 32 ]) v += 32; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 16 ]) v += 16; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 8 ]) v += 8; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 4 ]) v += 4; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 2 ]) v += 2; - if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 1 ]) v += 1; - return (unsigned char) v; + // Everything below 128 is off by 1. This fixes that. + int fix = 0; + + // Adding 1 to 0 with the fix gives incorrect results for input 0. This fixes that. + if (x < 81000) + return 0; + + i = 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; else fix = 1; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (unsigned char)v + fix; } static float stbir__filter_box(float x) @@ -1246,7 +1255,6 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void int output_pixel_index = x*channels; int encode_pixel_index = x*channels; - for (n = 0; n < channels; n++) ((unsigned char*)output_buffer)[output_pixel_index + n] = stbir__linear_to_srgb_uchar(encode_buffer[encode_pixel_index + n]); diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index 7234048..3ab2a00 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -734,6 +734,9 @@ void test_suite(int argc, char **argv) } #endif + for (i = 0; i < 256; i++) + STBIR_ASSERT(stbir__linear_to_srgb_uchar(stbir__srgb_to_linear(float(i)/255)) == i); + #if 0 // linear_to_srgb_uchar table for (i=0; i < 256; ++i) { float f = stbir__srgb_to_linear((i+0.5f)/256.0f);