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.
digikam/digikam/imageplugins/hotpixels/blackframeparser.cpp

212 lines
6.1 KiB

/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-03-27
* Description : black frames parser
*
* Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
* Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* Part of the algorithm for finding the hot pixels was based on
* the code of jpegpixi, which was released under the GPL license,
* and is Copyright (C) 2003, 2004 Martin Dickopp
*
* 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, 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.
*
* ============================================================ */
// Denominator for relative quantities.
#define DENOM (DENOM_STQRT * DENOM_STQRT)
// Square root of denominator for relative quantities.
#define DENOM_STQRT 10000
// Convert relative to absolute numbers. Care must be taken not to overflow integers.
#define REL_TO_ABS(n,m) \
((((n) / DENOM_STQRT) * (m) + ((n) % DENOM_STQRT) * (m) / DENOM_STQRT) / DENOM_STQRT)
// TQt includes.
#include <tqimage.h>
#include <tqstringlist.h>
// KDE includes.
#include <kapplication.h>
#include <tdeversion.h>
#include <tdeio/netaccess.h>
#include <tdeio/job.h>
// Local includes.
#include "blackframeparser.h"
#include "blackframeparser.moc"
namespace DigikamHotPixelsImagesPlugin
{
BlackFrameParser::BlackFrameParser(TQObject *parent)
: TQObject(parent)
{
m_imageLoaderThread = 0;
}
BlackFrameParser::~BlackFrameParser()
{
delete m_imageLoaderThread;
}
void BlackFrameParser::parseHotPixels(const TQString &file)
{
parseBlackFrame(KURL(file));
}
void BlackFrameParser::parseBlackFrame(const KURL &url)
{
#if KDE_IS_VERSION(3,2,0)
TDEIO::NetAccess::download(url, m_localFile, kapp->activeWindow());
#else
TDEIO::NetAccess::download(url, m_localFile);
#endif
if (!m_imageLoaderThread)
{
m_imageLoaderThread = new LoadSaveThread();
connect(m_imageLoaderThread, TQT_SIGNAL(signalLoadingProgress(const LoadingDescription&, float)),
this, TQT_SLOT(slotLoadingProgress(const LoadingDescription&, float)));
connect(m_imageLoaderThread, TQT_SIGNAL(signalImageLoaded(const LoadingDescription&, const DImg&)),
this, TQT_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg&)));
}
LoadingDescription desc = LoadingDescription(m_localFile, DRawDecoding());
m_imageLoaderThread->load(desc);
}
void BlackFrameParser::slotLoadingProgress(const LoadingDescription&, float v)
{
emit signalLoadingProgress(v);
}
void BlackFrameParser::slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg& img)
{
DImg image(img);
m_Image = image.copyTQImage();
blackFrameParsing();
emit signalLoadingComplete();
}
void BlackFrameParser::parseBlackFrame(TQImage& img)
{
m_Image = img;
blackFrameParsing();
}
// Parses black frames
void BlackFrameParser::blackFrameParsing()
{
// Now find the hot pixels and store them in a list
TQValueList<HotPixel> hpList;
for (int y=0 ; y < m_Image.height() ; ++y)
{
for (int x=0 ; x < m_Image.width() ; ++x)
{
//Get each point in the image
TQRgb pixrgb = m_Image.pixel(x,y);
TQColor color; color.setRgb(pixrgb);
// Find maximum component value.
int maxValue;
int threshold = DENOM/10;
const int threshold_value = REL_TO_ABS(threshold, 255);
maxValue = (color.red()>color.blue()) ? color.red() : color.blue();
if (color.green() > maxValue) maxValue = color.green();
// If the component is bigger than the threshold, add the point
if (maxValue > threshold_value)
{
HotPixel point;
point.rect = TQRect (x, y, 1, 1);
//TODO:check this
point.luminosity = ((2 * DENOM) / 255 ) * maxValue / 2;
hpList.append(point);
}
}
}
//Now join points together into groups
consolidatePixels (hpList);
//And notify
emit parsed(hpList);
}
// Consolidate adjacent points into larger points.
void BlackFrameParser::consolidatePixels (TQValueList<HotPixel>& list)
{
if (list.isEmpty())
return;
/* Consolidate horizontally. */
TQValueList<HotPixel>::iterator it, prevPointIt;
prevPointIt = list.begin();
it = list.begin();
++it;
HotPixel tmp;
HotPixel point;
HotPixel point_below;
TQValueList<HotPixel>::iterator end(list.end());
for (; it != end; ++it )
{
while (1)
{
point = (*it);
tmp = point;
TQValueList<HotPixel>::Iterator point_below_it;
point_below_it = list.find (tmp); //find any intersecting hotp below tmp
if (point_below_it != list.end())
{
point_below =* point_below_it;
validateAndConsolidate (&point, &point_below);
point.rect.setX(MIN(point.x(), point_below.x()));
point.rect.setWidth(MAX(point.x() + point.width(),
point_below.x() + point_below.width()) - point.x());
point.rect.setHeight(MAX(point.y() + point.height(),
point_below.y() + point_below.height()) - point.y());
*it = point;
list.remove (point_below_it); //TODO: Check! this could remove it++?
}
else
break;
}
}
}
void BlackFrameParser::validateAndConsolidate (HotPixel *a, HotPixel *b)
{
a->luminosity = MAX (a->luminosity, b->luminosity);
}
} // NameSpace DigikamHotPixelsImagesPlugin