From 0b692ca1b027fd082014471f8ead3afe5e7fbf9e Mon Sep 17 00:00:00 2001 From: JucaBlues Date: Sat, 20 Jun 2009 11:49:01 +0000 Subject: [PATCH] parsing and handling of icc-color in feFlood SVG Filters TODO: implement interface to set icc-color to the flood-color parameter --- src/display/nr-filter-flood.cpp | 27 +++++++++++--- src/display/nr-filter-flood.h | 3 ++ src/filters/flood.cpp | 25 +++++++++++-- src/filters/flood.h | 2 ++ src/svg/svg-color.cpp | 47 ++++++++++++++++++++++-- src/svg/svg-color.h | 1 + src/widgets/sp-color-icc-selector.cpp | 52 +++++++++++++-------------- 7 files changed, 122 insertions(+), 35 deletions(-) diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp index 026cbce16..06025392b 100644 --- a/src/display/nr-filter-flood.cpp +++ b/src/display/nr-filter-flood.cpp @@ -9,8 +9,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "display/nr-filter-flood.h" #include "display/nr-filter-utils.h" +#include "svg/svg-icc-color.h" +#include "svg/svg-color.h" namespace Inkscape { namespace Filters { @@ -26,6 +32,7 @@ FilterFlood::~FilterFlood() {} int FilterFlood::render(FilterSlot &slot, FilterUnits const &/*units*/) { +g_message("rendering feflood"); NRPixBlock *in = slot.get(_input); if (!in) { g_warning("Missing source image for feFlood (in=%d)", _input); @@ -43,12 +50,18 @@ int FilterFlood::render(FilterSlot &slot, FilterUnits const &/*units*/) { true); unsigned char *out_data = NR_PIXBLOCK_PX(out); - unsigned char r,g,b,a; - r = CLAMP_D_TO_U8((color >> 24) % 256); - g = CLAMP_D_TO_U8((color >> 16) % 256); - b = CLAMP_D_TO_U8((color >> 8) % 256); - a = CLAMP_D_TO_U8(opacity*255); + + + r = CLAMP_D_TO_U8((color >> 24) % 256); + g = CLAMP_D_TO_U8((color >> 16) % 256); + b = CLAMP_D_TO_U8((color >> 8) % 256); + a = CLAMP_D_TO_U8(opacity*255); + +#if ENABLE_LCMS + icc_color_to_sRGB(icc, &r, &g, &b); +g_message("result: r:%d g:%d b:%d", r, g, b); +#endif //ENABLE_LCMS for(i=0; i < 4*in_h*in_w; i+=4){ out_data[i]=r; @@ -70,6 +83,10 @@ void FilterFlood::set_opacity(double o) { opacity = o; } +void FilterFlood::set_icc(SVGICCColor *icc_color) { + icc = icc_color; +} + void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/) { } diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h index 9e6a53abb..d38c0d4f5 100644 --- a/src/display/nr-filter-flood.h +++ b/src/display/nr-filter-flood.h @@ -15,6 +15,7 @@ #include "display/nr-filter-primitive.h" #include "display/nr-filter-slot.h" #include "display/nr-filter-units.h" +#include "svg/svg-color.h" namespace Inkscape { namespace Filters { @@ -27,11 +28,13 @@ public: virtual void set_opacity(double o); virtual void set_color(guint32 c); + virtual void set_icc(SVGICCColor *icc_color); virtual int render(FilterSlot &slot, FilterUnits const &units); virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); private: double opacity; guint32 color; + SVGICCColor *icc; }; } /* namespace Filters */ diff --git a/src/filters/flood.cpp b/src/filters/flood.cpp index 625e35d42..221b0daf2 100644 --- a/src/filters/flood.cpp +++ b/src/filters/flood.cpp @@ -17,12 +17,13 @@ # include "config.h" #endif +#include "strneq.h" + #include "attributes.h" #include "svg/svg.h" #include "flood.h" #include "xml/repr.h" #include "helper-fns.h" -#include "svg/svg-color.h" /* FeFlood base class */ @@ -79,6 +80,7 @@ static void sp_feFlood_init(SPFeFlood *feFlood) { feFlood->opacity = 1; + feFlood->icc = NULL; } /** @@ -120,16 +122,34 @@ sp_feFlood_set(SPObject *object, unsigned int key, gchar const *value) gchar *end_ptr = NULL; guint32 read_color; double read_num; + bool dirty = false; switch(key) { /*DEAL WITH SETTING ATTRIBUTES HERE*/ case SP_PROP_FLOOD_COLOR: cend_ptr = NULL; read_color = sp_svg_read_color(value, &cend_ptr, 0xffffffff); + if (cend_ptr && read_color != feFlood->color){ feFlood->color = read_color; - object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + dirty=true; + } + + if (cend_ptr){ + while (g_ascii_isspace(*cend_ptr)) { + ++cend_ptr; + } + if (strneq(cend_ptr, "icc-color(", 10)) { + if (!feFlood->icc) feFlood->icc = new SVGICCColor(); + if ( ! sp_svg_read_icc_color( cend_ptr, feFlood->icc ) ) { + delete feFlood->icc; + feFlood->icc = NULL; + } + dirty = true; + } } + if (dirty) + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); break; case SP_PROP_FLOOD_OPACITY: if (value) { @@ -208,6 +228,7 @@ static void sp_feFlood_build_renderer(SPFilterPrimitive *primitive, Inkscape::Fi nr_flood->set_opacity(sp_flood->opacity); nr_flood->set_color(sp_flood->color); + nr_flood->set_icc(sp_flood->icc); } diff --git a/src/filters/flood.h b/src/filters/flood.h index 046c0e868..f386e2cd4 100644 --- a/src/filters/flood.h +++ b/src/filters/flood.h @@ -15,6 +15,7 @@ #include "sp-filter.h" #include "flood-fns.h" +#include "svg/svg-icc-color.h" #include "display/nr-filter.h" #include "display/nr-filter-flood.h" @@ -25,6 +26,7 @@ class SPFeFloodClass; struct SPFeFlood : public SPFilterPrimitive { /** FLOOD ATTRIBUTES HERE */ guint32 color; + SVGICCColor *icc; double opacity; }; diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp index 743d2bbc8..fcfbbdbd8 100644 --- a/src/svg/svg-color.cpp +++ b/src/svg/svg-color.cpp @@ -36,6 +36,15 @@ #include "svg-color.h" #include "svg-icc-color.h" +#if ENABLE_LCMS +#include +#include "color.h" +#include "color-profile.h" +#include "document.h" +#include "inkscape.h" +#include "profile-manager.h" +#endif // ENABLE_LCMS + using std::sprintf; struct SPSVGColor { @@ -454,6 +463,39 @@ sp_svg_create_color_hash() return colors; } +//helper function borrowed from src/widgets/sp-color-icc-selector.cpp: +void getThings( DWORD space, gchar const**& namers, gchar const**& tippies, guint const*& scalies ); + +void icc_color_to_sRGB(SVGICCColor* icc, guchar* r, guchar* g, guchar* b){ + guchar color_out[4]; + guchar color_in[4]; + if (icc){ +g_message("profile name: %s", icc->colorProfile.c_str()); + Inkscape::ColorProfile* prof = SP_ACTIVE_DOCUMENT->profileManager->find(icc->colorProfile.c_str()); + if ( prof ) { + cmsHTRANSFORM trans = prof->getTransfToSRGB8(); + if ( trans ) { + gchar const** names = 0; + gchar const** tips = 0; + guint const* scales = 0; + getThings( prof->getColorSpace(), names, tips, scales ); + + guint count = _cmsChannelsOf( prof->getColorSpace() ); + if (count>4) count=4; //do we need it? Should we allow an arbitrary number of color values? Or should we limit to a maximum? (max==4?) + for (guint i=0;icolors[i])*256.0) * (gdouble)scales[i]); +g_message("input[%d]: %d",i, color_in[i]); + } + + cmsDoTransform( trans, color_in, color_out, 1 ); +g_message("transform to sRGB done"); + } + *r = color_out[0]; + *g = color_out[1]; + *b = color_out[2]; + } + } +} bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor* dest ) { @@ -508,6 +550,7 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor if ( !errno ) { if ( dest ) { dest->colors.push_back( dbl ); +g_message("color: %f", dbl); } str = endPtr; } else { @@ -529,7 +572,7 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor while ( g_ascii_isspace(*str) ) { str++; } - good &= *str == ')'; + good &= (*str == ')'); } } @@ -550,7 +593,7 @@ bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest ) { - sp_svg_read_icc_color(str, NULL, dest); + return sp_svg_read_icc_color(str, NULL, dest); } /* diff --git a/src/svg/svg-color.h b/src/svg/svg-color.h index d1238dcab..a3868c149 100644 --- a/src/svg/svg-color.h +++ b/src/svg/svg-color.h @@ -11,5 +11,6 @@ void sp_svg_write_color(char *buf, unsigned int buflen, unsigned int rgba32); bool sp_svg_read_icc_color( gchar const *str, gchar const **end_ptr, SVGICCColor* dest ); bool sp_svg_read_icc_color( gchar const *str, SVGICCColor* dest ); +void icc_color_to_sRGB(SVGICCColor* dest, guchar* r, guchar* g, guchar* b); #endif /* !SVG_SVG_COLOR_H_SEEN */ diff --git a/src/widgets/sp-color-icc-selector.cpp b/src/widgets/sp-color-icc-selector.cpp index 144e42aa2..ae837117a 100644 --- a/src/widgets/sp-color-icc-selector.cpp +++ b/src/widgets/sp-color-icc-selector.cpp @@ -22,15 +22,15 @@ #if ENABLE_LCMS #include "color-profile-fns.h" #include "color-profile.h" -//#define DEBUG_LCMS -#if 1 //DEBUG_LCMS +#define DEBUG_LCMS +#ifdef DEBUG_LCMS #include "preferences.h" #include #endif // DEBUG_LCMS #endif // ENABLE_LCMS -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS extern guint update_in_progress; #define DEBUG_MESSAGE(key, ...) \ {\ @@ -475,11 +475,11 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) if ( name ) { if ( tmp.icc && tmp.icc->colorProfile == name ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Already at name [%s]", name ); #endif // DEBUG_LCMS } else { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Need to switch to profile [%s]", name ); #endif // DEBUG_LCMS if ( tmp.icc ) { @@ -498,12 +498,12 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) SP_RGBA32_G_U(val), SP_RGBA32_B_U(val), 255}; -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Shoving in [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); #endif // DEBUG_LCMS icUInt16Number post[4] = {0,0,0,0}; cmsDoTransform( trans, pre, post, 1 ); -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("got on out [%04x] [%04x] [%04x] [%04x]", post[0], post[1], post[2], post[3]); #endif // DEBUG_LCMS guint count = _cmsChannelsOf( newProf->getColorSpace() ); @@ -515,7 +515,7 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) for ( guint i = 0; i < count; i++ ) { gdouble val = (((gdouble)post[i])/65535.0) * (gdouble)scales[i]; -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message(" scaled %d by %d to be %f", i, scales[i], val); #endif // DEBUG_LCMS tmp.icc->colors.push_back(val); @@ -523,7 +523,7 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) cmsHTRANSFORM retrans = newProf->getTransfToSRGB8(); if ( retrans ) { cmsDoTransform( retrans, post, pre, 1 ); -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message(" back out [%02x] [%02x] [%02x]", pre[0], pre[1], pre[2]); #endif // DEBUG_LCMS tmp.set(SP_RGBA32_U_COMPOSE(pre[0], pre[1], pre[2], 0xff)); @@ -533,7 +533,7 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) dirty = true; } } else { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("NUKE THE ICC"); #endif // DEBUG_LCMS if ( tmp.icc ) { @@ -542,21 +542,21 @@ void ColorICCSelector::_switchToProfile( gchar const* name ) dirty = true; _fixupHit( 0, this ); } else { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("No icc to nuke"); #endif // DEBUG_LCMS } } if ( dirty ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("+----------------"); g_message("+ new color is [%s]", tmp.toString().c_str()); #endif // DEBUG_LCMS _setProfile( tmp.icc ); //_adjustmentChanged( _fooAdj[0], SP_COLOR_ICC_SELECTOR(_csel) ); setColorAlpha( tmp, _alpha, true ); -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("+_________________"); #endif // DEBUG_LCMS } @@ -605,13 +605,13 @@ void ColorICCSelector::_colorChanged() _updating = TRUE; //sp_color_icc_set_color( SP_COLOR_ICC( _icc ), &color ); -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "/^^^^^^^^^ %p::_colorChanged(%08x:%s)", this, _color.toRGBA32(_alpha), ( (_color.icc) ? _color.icc->colorProfile.c_str(): "" ) ); #endif // DEBUG_LCMS -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("FLIPPIES!!!! %p '%s'", _color.icc, (_color.icc ? _color.icc->colorProfile.c_str():"")); #endif // DEBUG_LCMS @@ -642,7 +642,7 @@ void ColorICCSelector::_colorChanged() if ( other != _color.toRGBA32(255) ) { _fixupNeeded = other; gtk_widget_set_sensitive( _fixupBtn, TRUE ); -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Color needs to change 0x%06x to 0x%06x", _color.toRGBA32(255) >> 8, other >> 8 ); #endif // DEBUG_LCMS } @@ -654,7 +654,7 @@ void ColorICCSelector::_colorChanged() _updating = FALSE; -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "\\_________ %p::_colorChanged()", this ); #endif // DEBUG_LCMS } @@ -662,7 +662,7 @@ void ColorICCSelector::_colorChanged() #if ENABLE_LCMS void ColorICCSelector::_setProfile( SVGICCColor* profile ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "/^^^^^^^^^ %p::_setProfile(%s)", this, ( (profile) ? profile->colorProfile.c_str() : "") ); @@ -730,7 +730,7 @@ void ColorICCSelector::_setProfile( SVGICCColor* profile ) } } -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "\\_________ %p::_setProfile()", this ); #endif // DEBUG_LCMS } @@ -800,7 +800,7 @@ void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICC // gtk_adjustment_set_value( adjustment, floor ((adjustment->value) * adjustment->upper + 0.5) ); // } -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "/^^^^^^^^^ %p::_adjustmentChanged()", cs ); #endif // DEBUG_LCMS @@ -816,7 +816,7 @@ void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICC SPColor newColor( iccSelector->_color ); gfloat scaled = ColorScales::getScaled( iccSelector->_adj ); if ( iccSelector->_adj == adjustment ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("ALPHA"); #endif // DEBUG_LCMS } else { @@ -828,7 +828,7 @@ void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICC } } if ( match >= 0 ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message(" channel %d", match ); #endif // DEBUG_LCMS } @@ -852,7 +852,7 @@ void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICC guint32 newer = other.toRGBA32(255); if ( prior != newer ) { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Transformed color from 0x%08x to 0x%08x", prior, newer ); g_message(" ~~~~ FLIP"); #endif // DEBUG_LCMS @@ -875,7 +875,7 @@ void ColorICCSelector::_adjustmentChanged( GtkAdjustment *adjustment, SPColorICC iccSelector->_updateSliders( match ); iccSelector->_updating = FALSE; -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message( "\\_________ %p::_adjustmentChanged()", cs ); #endif // DEBUG_LCMS } @@ -900,13 +900,13 @@ void ColorICCSelector::_sliderReleased( SPColorSlider */*slider*/, SPColorICCSel // } } -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS void ColorICCSelector::_sliderChanged( SPColorSlider *slider, SPColorICCSelector *cs ) #else void ColorICCSelector::_sliderChanged( SPColorSlider */*slider*/, SPColorICCSelector */*cs*/ ) #endif // DEBUG_LCMS { -#if 1 //DEBUG_LCMS +#ifdef DEBUG_LCMS g_message("Changed %p and %p", slider, cs ); #endif // DEBUG_LCMS // ColorICCSelector* iccSelector = (ColorICCSelector*)(SP_COLOR_SELECTOR(cs)->base); -- 2.30.2