summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJasper van de Gronde <jasper.vandegronde@gmail.com>2008-12-20 16:53:19 +0000
committerjaspervdg <jaspervdg@users.sourceforge.net>2008-12-20 16:53:19 +0000
commitb5f8e459ea83a6c640e5b08048b698137404fd57 (patch)
treeaccd6191a39e6844e0b60ba17b59cfa87093c11e /src
parentFixes "disappearing gradients" problem discussed on mailing list and adds a f... (diff)
downloadinkscape-b5f8e459ea83a6c640e5b08048b698137404fd57.tar.gz
inkscape-b5f8e459ea83a6c640e5b08048b698137404fd57.zip
Some accuracy improvements for ComponentTransfer filters (should also be somewhat faster).
(bzr r7019)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-component-transfer.cpp35
1 files changed, 26 insertions, 9 deletions
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 5c4fd4598..dbf5c44ed 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -14,6 +14,7 @@
#include "display/nr-filter-utils.h"
#include "libnr/nr-pixblock.h"
#include "libnr/nr-blit.h"
+#include "libnr/nr-pixops.h"
#include <math.h>
namespace NR {
@@ -70,12 +71,11 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
for (int color=0;color<4;color++){
int _vsize = tableValues[color].size();
- std::vector<gdouble> _tableValues = tableValues[color];
double _intercept = intercept[color];
double _slope = slope[color];
double _amplitude = amplitude[color];
double _exponent = exponent[color];
- double _offset = offset[color];
+ double _offset = offset[color];
switch(type[color]){
case COMPONENTTRANSFER_TYPE_IDENTITY:
for(i=color;i<size;i+=4){
@@ -83,15 +83,23 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
}
break;
case COMPONENTTRANSFER_TYPE_TABLE:
- if (_vsize==0){
+ if (_vsize<=1){
+ if (_vsize==1) {
+ g_warning("A component transfer table has to have at least two values.");
+ }
for(i=color;i<size;i+=4){
out_data[i]=in_data[i];
}
} else {
+ std::vector<gdouble> _tableValues(tableValues[color]);
+ // Scale by 255 and add .5 to avoid having to add it later for rounding purposes
+ for(i=0;i<_vsize;i++) {
+ _tableValues[i] = std::max(0.,std::min(255.,255*_tableValues[i])) + .5;
+ }
for(i=color;i<size;i+=4){
- int k = (int)(((_vsize-1) * (double)in_data[i])/256);
- double dx = ((_vsize-1) * (double)in_data[i])/256 - k;
- out_data[i] = CLAMP_D_TO_U8(256 * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k]) ));
+ int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]);
+ double dx = ((_vsize-1) * in_data[i])/255.0 - k;
+ out_data[i] = static_cast<unsigned char>(_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k]));
}
}
break;
@@ -101,19 +109,28 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units
out_data[i] = in_data[i];
}
} else {
+ 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);
+ }
for(i=color;i<size;i+=4){
- out_data[i] = CLAMP_D_TO_U8(256 * _tableValues[(int)((_vsize-1)*(double)in_data[i]/256)] );
+ int k = FAST_DIVIDE<255>((_vsize-1) * in_data[i]);
+ out_data[i] = _tableValues[k];
}
}
break;
case COMPONENTTRANSFER_TYPE_LINEAR:
+ _intercept = 255*_intercept + .5;
for(i=color;i<size;i+=4){
- out_data[i] = CLAMP_D_TO_U8(256 * (_slope * (double)in_data[i]/256 + _intercept));
+ out_data[i] = CLAMP_D_TO_U8(_slope * in_data[i] + _intercept);
}
break;
case COMPONENTTRANSFER_TYPE_GAMMA:
+ _amplitude *= pow(255.0, -_exponent+1);
+ _offset = 255*_offset + .5;
for(i=color;i<size;i+=4){
- out_data[i] = CLAMP_D_TO_U8(256 * (_amplitude * pow((double)in_data[i]/256, _exponent) + _offset));
+ out_data[i] = CLAMP_D_TO_U8(_amplitude * pow((double)in_data[i], _exponent) + _offset);
}
break;
case COMPONENTTRANSFER_TYPE_ERROR: