Code

Fixes some wrong uses of CLAMP_D_TO_U8 in filtering code (mostly based on my misunder...
authorjaspervdg <jaspervdg@users.sourceforge.net>
Sun, 5 Apr 2009 19:45:12 +0000 (19:45 +0000)
committerjaspervdg <jaspervdg@users.sourceforge.net>
Sun, 5 Apr 2009 19:45:12 +0000 (19:45 +0000)
src/display/nr-filter-colormatrix.cpp
src/display/nr-filter-component-transfer.cpp
src/display/nr-filter-composite.cpp
src/display/nr-filter-convolve-matrix.cpp
src/display/nr-filter-diffuselighting.cpp
src/display/nr-filter-specularlighting.cpp
src/display/nr-filter-turbulence.cpp
src/display/nr-filter-utils.h

index 21e659a6ad7ead194477bb5d35c3bf2930a3e953..66fb196cb9740a42a71c0a27e0a3dca8f45143e1 100644 (file)
@@ -91,7 +91,7 @@ int FilterColorMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
                         g = in_data[i+1];
                         b = in_data[i+2];
                         a = in_data[i+3];
-                        out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + a04 );
+                        out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + a04 ); // CLAMP includes rounding!
                         out_data[i+1] = CLAMP_D_TO_U8( r*values[5] + g*values[6] + b*values[7] + a*values[8] + a14 );
                         out_data[i+2] = CLAMP_D_TO_U8( r*values[10] + g*values[11] + b*values[12] + a*values[13] + a24 );
                         out_data[i+3] = CLAMP_D_TO_U8( r*values[15] + g*values[16] + b*values[17] + a*values[18] + a34 );
index bd52c071ed7bf1d073799390da54dcc30ed6fd6f..87f87c95ab981b4c34ac920648ddb7b6eda2d99c 100644 (file)
@@ -98,6 +98,7 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
                     if (!premultiplied || color==3) {
                         std::vector<gdouble> _tableValues(tableValues[color]);
                         // Scale by 255 and add .5 to avoid having to add it later for rounding purposes
+                        //   Note that this means that CLAMP_D_TO_U8 cannot be used here (as it includes rounding!)
                         for(i=0;i<_vsize;i++) {
                             _tableValues[i] = std::max(0.,std::min(255.,255*_tableValues[i])) + .5;
                         }
@@ -115,7 +116,7 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
                             if (in_data[i+3-color]==0) continue;
                             int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color];
                             double dx = ((_vsize-1) * in_data[i]) / (double)in_data[i+3-color] - k;
-                            out_data[i] = static_cast<unsigned char>(out_data[i+3-color] * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])) + .5);
+                            out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k])), out_data[i+3-color]); // CLAMP includes rounding!
                         }
                     }
                 }
@@ -130,7 +131,7 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
                         std::vector<unsigned char> _tableValues(_vsize);
                         // Convert to unsigned char
                         for(i=0;i<_vsize;i++) {
-                            _tableValues[i] = static_cast<unsigned char>(std::max(0.,std::min(255.,255*tableValues[color][i])) + .5);
+                            _tableValues[i] = CLAMP_D_TO_U8(255*tableValues[color][i]);
                         }
                         for(i=color;i<size;i+=4){
                             int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]);
@@ -144,35 +145,37 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
                         for(i=color;i<size;i+=4){
                             if (in_data[i+3-color]==0) continue;
                             int k = ((_vsize-1) * in_data[i]) / in_data[i+3-color];
-                            out_data[i] =  static_cast<unsigned char>(out_data[i+3-color] * _tableValues[k] + .5);
+                            out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * _tableValues[k], out_data[i+3-color]);
                         }
                     }
                 }
                 break;
             case COMPONENTTRANSFER_TYPE_LINEAR:
                 if (!premultiplied || color==3) {
-                    _intercept = 255*_intercept + .5;
+                    _intercept = 255*_intercept;
                     for(i=color;i<size;i+=4){
-                        out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept);
+                        out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept); // CLAMP includes rounding!
                     }
                 } else {
                     for(i=color;i<size;i+=4){
                         if (in_data[i+3-color]==0) continue;
-                        out_data[i] = CLAMP_D_TO_U8(out_data[i+3-color] * (_slope * in_data[i] / in_data[i+3-color] + _intercept) + .5);
+                        double out = _slope * in_data[i] / in_data[i+3-color] + _intercept;
+                        out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * out, out_data[i+3-color]);
                     }
                 }
                 break;
             case COMPONENTTRANSFER_TYPE_GAMMA:
                 if (!premultiplied || color==3) {
                     _amplitude *= pow(255.0, -_exponent+1); // The input should be divided by 255, then exponentiated and then multiplied by 255 again, instead the amplitude is modified accordingly.
-                    _offset = 255*_offset + .5;
+                    _offset = 255*_offset;
                     for(i=color;i<size;i+=4){
                         out_data[i] = CLAMP_D_TO_U8(_amplitude * pow((double)in_data[i], _exponent) + _offset);
                     }
                 } else {
                     for(i=color;i<size;i+=4){
                         if (in_data[i+3-color]==0) continue;
-                        out_data[i] = CLAMP_D_TO_U8(out_data[i+3-color] * (_amplitude * pow((double)in_data[i] / in_data[i+3-color], _exponent) + _offset) + .5);
+                        double out = _amplitude * pow((double)in_data[i] / in_data[i+3-color], _exponent) + _offset;
+                        out_data[i] = CLAMP_D_TO_U8_ALPHA(out_data[i+3-color] * out, out_data[i+3-color]);
                     }
                 }
                 break;
index e68c0bd90f90d33a93c3ebaadad285e624311f6c..51652d743e562ed5ef0cf471687cf3ebc004121f 100644 (file)
@@ -154,10 +154,10 @@ int FilterComposite::render(FilterSlot &slot, FilterUnits const &/*units*/) {
             pixops_mix<composite_xor>(*out, *in1, *in2);
             break;
         case COMPOSITE_ARITHMETIC:
-            arith_k1 = (int)(k1 * 255);
-            arith_k2 = (int)(k2 * 255 * 255);
-            arith_k3 = (int)(k3 * 255 * 255);
-            arith_k4 = (int)(k4 * 255 * 255 * 255);
+            arith_k1 = (int)round(k1 * 255);
+            arith_k2 = (int)round(k2 * 255 * 255);
+            arith_k3 = (int)round(k3 * 255 * 255);
+            arith_k4 = (int)round(k4 * 255 * 255 * 255);
             pixops_mix<composite_arithmetic>(*out, *in1, *in2);
             break;
         case COMPOSITE_DEFAULT:
index 3fca952da14c22de01349f506ba4bf07a2b4fa3a..fc279df4ce0e3f8c5166cc886aace3dd652819e3 100644 (file)
@@ -78,7 +78,7 @@ int FilterConvolveMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/)
                 }
             }
             unsigned int out_index = 4*( x + width*y );
-            out_data[out_index++] = CLAMP_D_TO_U8(result_R / divisor + bias);
+            out_data[out_index++] = CLAMP_D_TO_U8(result_R / divisor + bias); // CLAMP includes rounding!
             out_data[out_index++] = CLAMP_D_TO_U8(result_G / divisor + bias);
             out_data[out_index++] = CLAMP_D_TO_U8(result_B / divisor + bias);
 
index bf5b97fb1310787039e99cfa002ddb66c0e48f32..8915c88b183218936da514186f8d99cd2d156e9c 100644 (file)
@@ -87,7 +87,7 @@ int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
                 NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 inter = kd * NR::scalar_product(N, L);
 
-                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); // CLAMP includes rounding!
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j++] = 255;
index 526f49ec8ba3633cdd8016dce42973632d8b79d7..b096ee49d2691c319567c75cde3853a90b0852de 100644 (file)
@@ -105,7 +105,7 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) {
                 NR::compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
                 COMPUTE_INTER(inter, N, H, ks, specularExponent);
 
-                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
+                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]); // CLAMP includes rounding!
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
                 data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
                 data_o[j] = MAX(MAX(data_o[j-3], data_o[j-2]), data_o[j-1]);
index 1336e5f79075f6655d2e41a0682b2ef9a11b5c7b..a91db3d56132d34977cf93c0e92e04381bbc9263 100644 (file)
@@ -100,7 +100,7 @@ void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, Filter
             for (int x = std::max(bbox_x0, pix->area.x0); x < std::min(bbox_x1, pix->area.x1); x++){
                 int out_pos = out_line + 4 * (x - pix->area.x0);
                 point[0] = x * unit_trans[0] + unit_trans[4];
-                pb[out_pos] = CLAMP_D_TO_U8( turbulence(0,point)*255 );
+                pb[out_pos] = CLAMP_D_TO_U8( turbulence(0,point)*255 ); // CLAMP includes rounding!
                 pb[out_pos + 1] = CLAMP_D_TO_U8( turbulence(1,point)*255 );
                 pb[out_pos + 2] = CLAMP_D_TO_U8( turbulence(2,point)*255 );
                 pb[out_pos + 3] = CLAMP_D_TO_U8( turbulence(3,point)*255 );
index c825a814ed00c58a7f634f8ee909ab87fb9cc9ab..5c59a0e8429cb4021c08b0c9207be1c481fb7c15 100644 (file)
@@ -64,6 +64,11 @@ inline int clamp_alpha(int const val, int const alpha) {
     return val;
 }
 
+/**
+ * Macro to use the clamp function with double inputs and unsigned char output
+ */
+#define CLAMP_D_TO_U8_ALPHA(v,a) (unsigned char) clamp_alpha((int)round((v)),(a))
+
 } /* namespace Filters */
 } /* namespace Inkscape */