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

394 lines
13 KiB

/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2005-05-25
* Description : border threaded image filter.
*
* Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright 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>
// TQt includes.
#include <tqpoint.h>
#include <tqregion.h>
#include <tqpointarray.h>
// Local includes.
#include "dimg.h"
#include "ddebug.h"
#include "border.h"
namespace DigikamBorderImagesPlugin
{
Border::Border(Digikam::DImg *image, TQObject *tqparent, int orgWidth, int orgHeight,
TQString borderPath, int borderType, float borderPercent,
Digikam::DColor solidColor,
Digikam::DColor niepceBorderColor,
Digikam::DColor niepceLineColor,
Digikam::DColor bevelUpperLeftColor,
Digikam::DColor bevelLowerRightColor,
Digikam::DColor decorativeFirstColor,
Digikam::DColor decorativeSecondColor)
: Digikam::DImgThreadedFilter(image, tqparent, "Border")
{
m_orgWidth = orgWidth;
m_orgHeight = orgHeight;
m_orgRatio = (float)m_orgWidth / (float)m_orgHeight;
m_borderType = borderType;
m_borderPath = borderPath;
int size = (image->width() > image->height()) ? image->height() : image->width();
m_borderMainWidth = (int)(size * borderPercent);
m_border2ndWidth = (int)(size * 0.005);
// Clamp internal border with to 1 pixel to be visible with small image.
if (m_border2ndWidth < 1) m_border2ndWidth = 1;
m_solidColor = solidColor;
m_niepceBorderColor = niepceBorderColor;
m_niepceLineColor = niepceLineColor;
m_bevelUpperLeftColor = bevelUpperLeftColor;
m_bevelLowerRightColor = bevelLowerRightColor;
m_decorativeFirstColor = decorativeFirstColor;
m_decorativeSecondColor = decorativeSecondColor;
m_preserveAspectRatio = true;
initFilter();
}
Border::Border(Digikam::DImg *orgImage, TQObject *tqparent, int orgWidth, int orgHeight,
TQString borderPath, int borderType,
int borderWidth1, int borderWidth2, int borderWidth3, int borderWidth4,
Digikam::DColor solidColor,
Digikam::DColor niepceBorderColor,
Digikam::DColor niepceLineColor,
Digikam::DColor bevelUpperLeftColor,
Digikam::DColor bevelLowerRightColor,
Digikam::DColor decorativeFirstColor,
Digikam::DColor decorativeSecondColor)
: Digikam::DImgThreadedFilter(orgImage, tqparent, "Border")
{
m_orgWidth = orgWidth;
m_orgHeight = orgHeight;
m_borderType = borderType;
m_borderWidth1 = borderWidth1;
m_borderWidth2 = borderWidth2;
m_borderWidth3 = borderWidth3;
m_borderWidth4 = borderWidth4;
m_solidColor = solidColor;
m_niepceBorderColor = niepceBorderColor;
m_niepceLineColor = niepceLineColor;
m_bevelUpperLeftColor = bevelUpperLeftColor;
m_bevelLowerRightColor = bevelLowerRightColor;
m_decorativeFirstColor = decorativeFirstColor;
m_decorativeSecondColor = decorativeSecondColor;
m_borderPath = borderPath;
m_preserveAspectRatio = false;
initFilter();
}
void Border::filterImage(void)
{
switch (m_borderType)
{
case SolidBorder:
if (m_preserveAspectRatio)
solid(m_orgImage, m_destImage, m_solidColor, m_borderMainWidth);
else
solid2(m_orgImage, m_destImage, m_solidColor, m_borderWidth1);
break;
case NiepceBorder:
if (m_preserveAspectRatio)
niepce(m_orgImage, m_destImage, m_niepceBorderColor, m_borderMainWidth,
m_niepceLineColor, m_border2ndWidth);
else
niepce2(m_orgImage, m_destImage, m_niepceBorderColor, m_borderWidth1,
m_niepceLineColor, m_borderWidth4);
break;
case BeveledBorder:
if (m_preserveAspectRatio)
bevel(m_orgImage, m_destImage, m_bevelUpperLeftColor,
m_bevelLowerRightColor, m_borderMainWidth);
else
bevel2(m_orgImage, m_destImage, m_bevelUpperLeftColor,
m_bevelLowerRightColor, m_borderWidth1);
break;
case PineBorder:
case WoodBorder:
case PaperBorder:
case ParqueBorder:
case IceBorder:
case LeafBorder:
case MarbleBorder:
case RainBorder:
case CratersBorder:
case DriedBorder:
case PinkBorder:
case StoneBorder:
case ChalkBorder:
case GraniteBorder:
case RockBorder:
case WallBorder:
if (m_preserveAspectRatio)
pattern(m_orgImage, m_destImage, m_borderMainWidth,
m_decorativeFirstColor, m_decorativeSecondColor,
m_border2ndWidth, m_border2ndWidth);
else
pattern2(m_orgImage, m_destImage, m_borderWidth1,
m_decorativeFirstColor, m_decorativeSecondColor,
m_borderWidth2, m_borderWidth2);
break;
}
}
// -- Methods to preserve aspect ratio of image ------------------------------------------
void Border::solid(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth)
{
if (m_orgWidth > m_orgHeight)
{
int height = src.height() + borderWidth*2;
dest = Digikam::DImg((int)(height*m_orgRatio), height, src.sixteenBit(), src.hasAlpha());
dest.fill(fg);
dest.bitBltImage(&src, (dest.width()-src.width())/2, borderWidth);
}
else
{
int width = src.width() + borderWidth*2;
dest = Digikam::DImg(width, (int)(width/m_orgRatio), src.sixteenBit(), src.hasAlpha());
dest.fill(fg);
dest.bitBltImage(&src, borderWidth, (dest.height()-src.height())/2);
}
}
void Border::niepce(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg,
int borderWidth, const Digikam::DColor &bg, int lineWidth)
{
Digikam::DImg tmp;
solid(src, tmp, bg, lineWidth);
solid(tmp, dest, fg, borderWidth);
}
void Border::bevel(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
const Digikam::DColor &btmColor, int borderWidth)
{
int width, height;
if (m_orgWidth > m_orgHeight)
{
height = src.height() + borderWidth*2;
width = (int)(height*m_orgRatio);
}
else
{
width = src.width() + borderWidth*2;
height = (int)(width/m_orgRatio);
}
dest = Digikam::DImg(width, height, src.sixteenBit(), src.hasAlpha());
dest.fill(topColor);
TQPointArray btTriangle(3);
btTriangle.setPoint(0, width, 0);
btTriangle.setPoint(1, 0, height);
btTriangle.setPoint(2, width, height);
TQRegion btRegion(btTriangle);
for(int x=0 ; x < width ; x++)
{
for(int y=0 ; y < height ; y++)
{
if (btRegion.contains(TQPoint(x, y)))
dest.setPixelColor(x, y, btmColor);
}
}
if (m_orgWidth > m_orgHeight)
{
dest.bitBltImage(&src, (dest.width()-src.width())/2, borderWidth);
}
else
{
dest.bitBltImage(&src, borderWidth, (dest.height()-src.height())/2);
}
}
void Border::pattern(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth,
const Digikam::DColor &firstColor, const Digikam::DColor &secondColor,
int firstWidth, int secondWidth)
{
// Original image with the first solid border around.
Digikam::DImg tmp;
solid(src, tmp, firstColor, firstWidth);
// Border tiled image using pattern with second solid border around.
int width, height;
if (m_orgWidth > m_orgHeight)
{
height = tmp.height() + borderWidth*2;
width = (int)(height*m_orgRatio);
}
else
{
width = tmp.width() + borderWidth*2;
height = (int)(width/m_orgRatio);
}
Digikam::DImg tmp2(width, height, tmp.sixteenBit(), tmp.hasAlpha());
DDebug() << "Border File:" << m_borderPath << endl;
Digikam::DImg border(m_borderPath);
if ( border.isNull() )
return;
border.convertToDepthOfImage(&tmp2);
for (int x = 0 ; x < width ; x+=border.width())
for (int y = 0 ; y < height ; y+=border.height())
tmp2.bitBltImage(&border, x, y);
solid(tmp2, dest, secondColor, secondWidth);
// Merge both images to one.
if (m_orgWidth > m_orgHeight)
{
dest.bitBltImage(&tmp, (dest.width()-tmp.width())/2, borderWidth);
}
else
{
dest.bitBltImage(&tmp, borderWidth, (dest.height()-tmp.height())/2);
}
}
// -- Methods to not-preserve aspect ratio of image ------------------------------------------
void Border::solid2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth)
{
dest = Digikam::DImg(src.width() + borderWidth*2, src.height() + borderWidth*2,
src.sixteenBit(), src.hasAlpha());
dest.fill(fg);
dest.bitBltImage(&src, borderWidth, borderWidth);
}
void Border::niepce2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth,
const Digikam::DColor &bg, int lineWidth)
{
Digikam::DImg tmp;
solid2(src, tmp, bg, lineWidth);
solid2(tmp, dest, fg, borderWidth);
}
void Border::bevel2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
const Digikam::DColor &btmColor, int borderWidth)
{
int x, y;
int wc;
dest = Digikam::DImg(src.width() + borderWidth*2,
src.height() + borderWidth*2,
src.sixteenBit(), src.hasAlpha());
// top
for(y=0, wc = (int)dest.width()-1; y < borderWidth; ++y, --wc)
{
for(x=0; x < wc; ++x)
dest.setPixelColor(x, y, topColor);
for(;x < (int)dest.width(); ++x)
dest.setPixelColor(x, y, btmColor);
}
// left and right
for(; y < (int)dest.height()-borderWidth; ++y)
{
for(x=0; x < borderWidth; ++x)
dest.setPixelColor(x, y, topColor);
for(x = (int)dest.width()-1; x > (int)dest.width()-borderWidth-1; --x)
dest.setPixelColor(x, y, btmColor);
}
// bottom
for(wc = borderWidth; y < (int)dest.height(); ++y, --wc)
{
for(x=0; x < wc; ++x)
dest.setPixelColor(x, y, topColor);
for(; x < (int)dest.width(); ++x)
dest.setPixelColor(x, y, btmColor);
}
dest.bitBltImage(&src, borderWidth, borderWidth);
}
void Border::pattern2(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth,
const Digikam::DColor &firstColor, const Digikam::DColor &secondColor,
int firstWidth, int secondWidth)
{
// Border tile.
int w = m_orgWidth + borderWidth*2;
int h = m_orgHeight + borderWidth*2;
DDebug() << "Border File:" << m_borderPath << endl;
Digikam::DImg border(m_borderPath);
if ( border.isNull() )
return;
Digikam::DImg borderImg(w, h, src.sixteenBit(), src.hasAlpha());
border.convertToDepthOfImage(&borderImg);
for (int x = 0 ; x < w ; x+=border.width())
for (int y = 0 ; y < h ; y+=border.height())
borderImg.bitBltImage(&border, x, y);
// First line around the pattern tile.
Digikam::DImg tmp = borderImg.smoothScale(src.width() + borderWidth*2,
src.height() + borderWidth*2 );
solid2(tmp, dest, firstColor, firstWidth);
// Second line around original image.
tmp.reset();
solid2(src, tmp, secondColor, secondWidth);
// Copy original image.
dest.bitBltImage(&tmp, borderWidth, borderWidth);
}
} // NameSpace DigikamBorderImagesPlugin