/* * This file is part of Chalk * * Copyright (c) 2004 Michael Thaler * * ported from digikam, Copyright 2004 by Gilles Caulier, * Original Emboss algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_multi_integer_filter_widget.h" #include "kis_emboss_filter.h" KisEmbossFilter::KisEmbossFilter() : KisFilter(id(), "emboss", i18n("&Emboss with Variable Depth...")) { } void KisEmbossFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect) { Q_UNUSED(dst); //read the filter configuration values from the KisFilterConfiguration object TQ_UINT32 embossdepth = ((KisEmbossFilterConfiguration*)configuration)->depth(); //the actual filter function from digikam. It needs a pointer to a TQ_UINT8 array //with the actual pixel data. Emboss(src, dst, rect, embossdepth); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the Emboss effect * * data => The image data in RGBA mode. * Width => Width of image. * Height => Height of image. * d => Emboss value * * Theory => This is an amazing effect. And the theory is very simple to * understand. You get the diference between the colors and * increase it. After this, get the gray tone */ void KisEmbossFilter::Emboss(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, int d) { float Depth = d / 10.0; int R = 0, G = 0, B = 0; uchar Gray = 0; int Width = rect.width(); int Height = rect.height(); setProgressTotalSteps(Height); setProgressStage(i18n("Applying emboss filter..."),0); KisHLineIteratorPixel it = src->createHLineIterator(rect.x(), rect.y(), rect.width(), false); KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), rect.y(), rect.width(), true); TQColor color1; TQColor color2; TQ_UINT8 opacity; TQ_UINT8 opacity2; for (int y = 0 ; !cancelRequested() && (y < Height) ; ++y) { for (int x = 0 ; !cancelRequested() && (x < Width) ; ++x, ++it, ++dstIt) { if (it.isSelected()) { // XXX: COLORSPACE_INDEPENDENCE opacity = 0; opacity2 = 0; src->colorSpace()->toTQColor(it.rawData(), &color1, &opacity); src->pixel(rect.x() + x + Lim_Max(x, 1, Width), rect.y() + y + Lim_Max(y, 1, Height), &color2, &opacity2); R = abs((int)((color1.red() - color2.red()) * Depth + (TQ_UINT8_MAX / 2))); G = abs((int)((color1.green() - color2.green()) * Depth + (TQ_UINT8_MAX / 2))); B = abs((int)((color1.blue() - color2.blue()) * Depth + (TQ_UINT8_MAX / 2))); Gray = CLAMP((R + G + B) / 3, 0, TQ_UINT8_MAX); dst->colorSpace()->fromTQColor(TQColor(Gray, Gray, Gray), opacity, dstIt.rawData()); } } it.nextRow(); dstIt.nextRow(); setProgress(y); } setProgressDone(); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* This function limits the max and min values * defined by the developer * * Now => Original value * Up => Increments * Max => Maximum value * * Theory => This function is used in some functions to limit the * "for step". E.g. I have a picture with 309 pixels (width), and * my "for step" is 5. All the code go alright until reachs the * w = 305, because in the next step w will go to 310, but we want * to analize all the pixels. So, this function will reduce the * "for step", when necessary, until reach the last possible value */ int KisEmbossFilter::Lim_Max (int Now, int Up, int Max) { --Max; while (Now > Max - Up) --Up; return (Up); } KisFilterConfigWidget * KisEmbossFilter::createConfigurationWidget(TQWidget* parent, KisPaintDeviceSP) { vKisIntegerWidgetParam param; param.push_back( KisIntegerWidgetParam( 10, 300, 30, i18n("Depth"), "depth" ) ); KisFilterConfigWidget * w = new KisMultiIntegerFilterWidget(parent, id().id().ascii(), id().id().ascii(), param ); TQ_CHECK_PTR(w); return w; } KisFilterConfiguration* KisEmbossFilter::configuration(TQWidget* nwidget) { KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget; if( widget == 0 ) { return new KisEmbossFilterConfiguration( 30 ); } else { return new KisEmbossFilterConfiguration( widget->valueAt( 0 ) ); } }