/* ============================================================ * * 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 * Copyright (C) 2006-2007 by Marcel Wiesweg * * 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 #include // 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