You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.0 KiB
207 lines
7.0 KiB
/*
|
|
* This file is part of Chalk
|
|
*
|
|
* Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
|
|
*
|
|
* 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 "fastcolortransfer.h"
|
|
|
|
#include <kgenericfactory.h>
|
|
#include <kurlrequester.h>
|
|
|
|
#include <kis_colorspace_factory_registry.h>
|
|
#include <kis_doc.h>
|
|
#include <kis_image.h>
|
|
#include <kis_iterators_pixel.h>
|
|
#include <kis_meta_registry.h>
|
|
#include <kis_paint_device.h>
|
|
|
|
#include "kis_wdg_fastcolortransfer.h"
|
|
#include "wdgfastcolortransfer.h"
|
|
|
|
typedef KGenericFactory<FastColorTransferPlugin> ChalkFastColorTransferFactory;
|
|
K_EXPORT_COMPONENT_FACTORY( chalkfastcolortransfer, ChalkFastColorTransferFactory( "chalk" ) )
|
|
|
|
|
|
FastColorTransferPlugin::FastColorTransferPlugin(TQObject *parent, const char *name, const TQStringList &)
|
|
: KParts::Plugin(parent, name)
|
|
{
|
|
setInstance(ChalkFastColorTransferFactory::instance());
|
|
|
|
kdDebug(41006) << "Color Transfer Filter plugin. Class: "
|
|
<< className()
|
|
<< ", Parent: "
|
|
<< parent -> className()
|
|
<< "\n";
|
|
|
|
if (parent->inherits("KisFilterRegistry")) {
|
|
KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(parent);
|
|
manager->add(new KisFilterFastColorTransfer());
|
|
}
|
|
}
|
|
|
|
FastColorTransferPlugin::~FastColorTransferPlugin()
|
|
{
|
|
}
|
|
|
|
KisFilterFastColorTransfer::KisFilterFastColorTransfer() : KisFilter(id(), "colors", i18n("&Color Transfer..."))
|
|
{
|
|
}
|
|
|
|
|
|
KisFilterConfigWidget * KisFilterFastColorTransfer::createConfigurationWidget(TQWidget* parent, KisPaintDeviceSP )
|
|
{
|
|
return new KisWdgFastColorTransfer(this, parent, "configuration of color to alpha");
|
|
}
|
|
|
|
KisFilterConfiguration* KisFilterFastColorTransfer::configuration(TQWidget* w)
|
|
{
|
|
KisWdgFastColorTransfer * wCTA = dynamic_cast<KisWdgFastColorTransfer*>(w);
|
|
KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
|
|
if(wCTA)
|
|
{
|
|
config->setProperty("filename", wCTA->widget()->fileNameURLRequester->url() );
|
|
}
|
|
return config;
|
|
}
|
|
|
|
void KisFilterFastColorTransfer::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
|
|
{
|
|
kdDebug() << "Start transfering color" << endl;
|
|
TQVariant value;
|
|
TQString fileName;
|
|
if (config && config->getProperty("filename", value))
|
|
{
|
|
fileName = value.toString();
|
|
} else {
|
|
kdDebug() << "No file name for the reference image was specified." << endl;
|
|
return;
|
|
}
|
|
|
|
KisPaintDeviceSP ref;
|
|
|
|
KisDoc d;
|
|
d.import(fileName);
|
|
KisImageSP importedImage = d.currentImage();
|
|
|
|
if(importedImage)
|
|
{
|
|
ref = importedImage->projection();
|
|
}
|
|
if(!ref)
|
|
{
|
|
kdDebug() << "No reference image was specified." << endl;
|
|
return;
|
|
}
|
|
|
|
// Convert ref and src to LAB
|
|
KisColorSpace* labCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("LABA"),"");
|
|
if(!labCS)
|
|
{
|
|
kdDebug() << "The LAB colorspace is not available." << endl;
|
|
return;
|
|
}
|
|
|
|
setProgressTotalSteps(5);
|
|
|
|
KisColorSpace* oldCS = src->colorSpace();
|
|
KisPaintDeviceSP srcLAB = new KisPaintDevice(*src.data());
|
|
srcLAB->convertTo(labCS);
|
|
ref->convertTo(labCS);
|
|
|
|
setProgress( 1 );
|
|
|
|
// Compute the means and sigmas of src
|
|
double meanL_src = 0., meanA_src = 0., meanB_src = 0.;
|
|
double sigmaL_src = 0., sigmaA_src = 0., sigmaB_src = 0.;
|
|
KisRectIteratorPixel srcLABIt = srcLAB->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false );
|
|
while(!srcLABIt.isDone())
|
|
{
|
|
const TQ_UINT16* data = reinterpret_cast<const TQ_UINT16*>(srcLABIt.oldRawData());
|
|
TQ_UINT32 L = data[0];
|
|
TQ_UINT32 A = data[1];
|
|
TQ_UINT32 B = data[2];
|
|
meanL_src += L;
|
|
meanA_src += A;
|
|
meanB_src += B;
|
|
sigmaL_src += L*L;
|
|
sigmaA_src += A*A;
|
|
sigmaB_src += B*B;
|
|
++srcLABIt;
|
|
}
|
|
|
|
setProgress( 3 );
|
|
|
|
double size = 1. / ( rect.width() * rect.height() );
|
|
meanL_src *= size;
|
|
meanA_src *= size;
|
|
meanB_src *= size;
|
|
sigmaL_src *= size;
|
|
sigmaA_src *= size;
|
|
sigmaB_src *= size;
|
|
kdDebug() << size << " " << meanL_src << " " << meanA_src << " " << meanB_src << " " << sigmaL_src << " " << sigmaA_src << " " << sigmaB_src << endl;
|
|
// Compute the means and sigmas of src
|
|
double meanL_ref = 0., meanA_ref = 0., meanB_ref = 0.;
|
|
double sigmaL_ref = 0., sigmaA_ref = 0., sigmaB_ref = 0.;
|
|
KisRectIteratorPixel refIt = ref->createRectIterator(0, 0, importedImage->width(), importedImage->height(), false );
|
|
while(!refIt.isDone())
|
|
{
|
|
const TQ_UINT16* data = reinterpret_cast<const TQ_UINT16*>(refIt.oldRawData());
|
|
TQ_UINT32 L = data[0];
|
|
TQ_UINT32 A = data[1];
|
|
TQ_UINT32 B = data[2];
|
|
meanL_ref += L;
|
|
meanA_ref += A;
|
|
meanB_ref += B;
|
|
sigmaL_ref += L*L;
|
|
sigmaA_ref += A*A;
|
|
sigmaB_ref += B*B;
|
|
++refIt;
|
|
}
|
|
|
|
setProgress( 4 );
|
|
|
|
size = 1. / ( importedImage->width() * importedImage->height() );
|
|
meanL_ref *= size;
|
|
meanA_ref *= size;
|
|
meanB_ref *= size;
|
|
sigmaL_ref *= size;
|
|
sigmaA_ref *= size;
|
|
sigmaB_ref *= size;
|
|
kdDebug() << size << " " << meanL_ref << " " << meanA_ref << " " << meanB_ref << " " << sigmaL_ref << " " << sigmaA_ref << " " << sigmaB_ref << endl;
|
|
|
|
// Transfer colors
|
|
dst->convertTo(labCS);
|
|
{
|
|
double coefL = sqrt((sigmaL_ref - meanL_ref * meanL_ref) / (sigmaL_src - meanL_src * meanL_src));
|
|
double coefA = sqrt((sigmaA_ref - meanA_ref * meanA_ref) / (sigmaA_src - meanA_src * meanA_src));
|
|
double coefB = sqrt((sigmaB_ref - meanB_ref * meanB_ref) / (sigmaB_src - meanB_src * meanB_src));
|
|
kdDebug() << coefL << " " << coefA << " " << coefB << endl;
|
|
KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
|
|
while(!dstIt.isDone())
|
|
{
|
|
TQ_UINT16* data = reinterpret_cast<TQ_UINT16*>(dstIt.rawData());
|
|
data[0] = (TQ_UINT16)CLAMP( ( (double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.);
|
|
data[1] = (TQ_UINT16)CLAMP( ( (double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.);
|
|
data[2] = (TQ_UINT16)CLAMP( ( (double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.);
|
|
++dstIt;
|
|
}
|
|
}
|
|
dst->convertTo(oldCS);
|
|
setProgressDone(); // Must be called even if you don't really support progression
|
|
}
|