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/texture/texture.cpp

182 lines
5.6 KiB

/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-05-25
* Description : Texture threaded image filter.
*
* Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
*
* 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.
*
* ============================================================ */
// C++ includes.
#include <cmath>
#include <cstdlib>
// Local includes.
#include "dimg.h"
#include "ddebug.h"
#include "texture.h"
namespace DigikamTextureImagesPlugin
{
Texture::Texture(Digikam::DImg *orgImage, TQObject *tqparent, int blendGain, TQString texturePath)
: Digikam::DImgThreadedFilter(orgImage, tqparent, "Texture")
{
m_blendGain = blendGain;
m_texturePath = texturePath;
initFilter();
}
// This method is based on the Simulate Texture Film tutorial from GimpGuru.org web site
// available at this url : http://www.gimpguru.org/Tutorials/SimulatedTexture/
//#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ( ( (t >> 8) + t ) >> 8))
inline static int intMult8(uint a, uint b)
{
uint t = a * b + 0x80;
return ((t >> 8) + t) >> 8;
}
inline static int intMult16(uint a, uint b)
{
uint t = a * b + 0x8000;
return ((t >> 16) + t) >> 16;
}
void Texture::filterImage(void)
{
// Texture tile.
int w = m_orgImage.width();
int h = m_orgImage.height();
int bytesDepth = m_orgImage.bytesDepth();
bool sixteenBit = m_orgImage.sixteenBit();
DDebug() << "Texture File: " << m_texturePath << endl;
Digikam::DImg texture(m_texturePath);
if ( texture.isNull() ) return;
Digikam::DImg textureImg(w, h, m_orgImage.sixteenBit(), m_orgImage.hasAlpha());
texture.convertToDepthOfImage(&textureImg);
for (int x = 0 ; x < w ; x+=texture.width())
for (int y = 0 ; y < h ; y+=texture.height())
textureImg.bitBltImage(&texture, x, y);
// Apply texture.
uchar* data = m_orgImage.bits();
uchar* pTeData = textureImg.bits();
uchar* pOutBits = m_destImage.bits();
uint offset;
Digikam::DColor teData, transData, inData, outData;
uchar *ptr, *dptr, *tptr;
int progress;
int blendGain;
if (sixteenBit)
blendGain = (m_blendGain + 1) * 256 - 1;
else
blendGain = m_blendGain;
// Make textured transparent tqlayout.
for (int x = 0; !m_cancel && x < w; x++)
{
for (int y = 0; !m_cancel && y < h; y++)
{
offset = x*bytesDepth + (y*w*bytesDepth);
ptr = data + offset;
tptr = pTeData + offset;
// Read color
teData.setColor(tptr, sixteenBit);
// in the old algorithm, this was
//teData.channel.red = (teData.channel.red * (255 - m_blendGain) +
// transData.channel.red * m_blendGain) >> 8;
// but transdata was uninitialized, its components were apparently 0,
// so I removed the part after the "+".
if (sixteenBit)
{
teData.blendInvAlpha16(blendGain);
}
else
{
teData.blendInvAlpha8(blendGain);
}
// Overwrite RGB.
teData.setPixel(tptr);
}
// Update progress bar in dialog.
progress = (int) (((double)x * 50.0) / w);
if (progress%5 == 0)
postProgress(progress);
}
// Merge tqlayout and image using overlay method.
for (int x = 0; !m_cancel && x < w; x++)
{
for (int y = 0; !m_cancel && y < h; y++)
{
offset = x*bytesDepth + (y*w*bytesDepth);
ptr = data + offset;
dptr = pOutBits + offset;
tptr = pTeData + offset;
inData.setColor (ptr, sixteenBit);
outData.setColor(dptr, sixteenBit);
teData.setColor (tptr, sixteenBit);
if (sixteenBit)
{
outData.setRed ( intMult16 (inData.red(), inData.red() + intMult16(2 * teData.red(), 65535 - inData.red()) ) );
outData.setGreen( intMult16 (inData.green(), inData.green() + intMult16(2 * teData.green(), 65535 - inData.green()) ) );
outData.setBlue ( intMult16 (inData.blue(), inData.blue() + intMult16(2 * teData.blue(), 65535 - inData.blue()) ) );
}
else
{
outData.setRed ( intMult8 (inData.red(), inData.red() + intMult8(2 * teData.red(), 255 - inData.red()) ) );
outData.setGreen( intMult8 (inData.green(), inData.green() + intMult8(2 * teData.green(), 255 - inData.green()) ) );
outData.setBlue ( intMult8 (inData.blue(), inData.blue() + intMult8(2 * teData.blue(), 255 - inData.blue()) ) );
}
outData.setAlpha( inData.alpha() );
outData.setPixel( dptr );
}
// Update progress bar in dialog.
progress = (int) (50.0 + ((double)x * 50.0) / w);
if (progress%5 == 0)
postProgress(progress);
}
}
} // NameSpace DigikamTextureImagesPlugin