diff options
Diffstat (limited to 'src/imageplugins/sheartool/shear.cpp')
-rw-r--r-- | src/imageplugins/sheartool/shear.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/imageplugins/sheartool/shear.cpp b/src/imageplugins/sheartool/shear.cpp new file mode 100644 index 00000000..29af5390 --- /dev/null +++ b/src/imageplugins/sheartool/shear.cpp @@ -0,0 +1,185 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date : 2005-07-18 + * Description : Shear threaded image filter. + * + * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com> + * + * Original Shear algorithms copyrighted 2005 by + * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot com>. + * + * 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. + * + * ============================================================ */ + +// Degrees to radian convertion coeff (PI/180). To optimize computation. +#define DEG2RAD 0.017453292519943 + +// C++ includes. + +#include <cmath> +#include <cstdlib> + +// Local includes. + +#include "dimg.h" +#include "dimgimagefilters.h" +#include "shear.h" + +namespace DigikamShearToolImagesPlugin +{ + +Shear::Shear(Digikam::DImg *orgImage, TQObject *parent, float hAngle, float vAngle, + bool antialiasing, TQColor backgroundColor, int orgW, int orgH) + : Digikam::DImgThreadedFilter(orgImage, parent, "sheartool") +{ + m_hAngle = hAngle; + m_vAngle = vAngle; + m_orgW = orgW; + m_orgH = orgH; + m_antiAlias = antialiasing; + m_backgroundColor = backgroundColor; + + initFilter(); +} + +void Shear::filterImage(void) +{ + int progress; + int x, y, p = 0, pt; + int new_width, new_height; + double nx, ny, dx, dy; + double horz_factor, vert_factor; + double horz_add, vert_add; + double horz_beta_angle, vert_beta_angle; + + int nWidth = m_orgImage.width(); + int nHeight = m_orgImage.height(); + + uchar *pBits = m_orgImage.bits(); + unsigned short *pBits16 = (unsigned short*)m_orgImage.bits(); + + // get beta ( complementary ) angle for horizontal and vertical angles + horz_beta_angle = ( ( ( m_hAngle < 0.0 ) ? 180.0 : 90.0 ) - m_hAngle ) * DEG2RAD; + vert_beta_angle = ( ( ( m_vAngle < 0.0 ) ? 180.0 : 90.0 ) - m_vAngle ) * DEG2RAD; + + // get new distance for width and height values + horz_add = nHeight * ( ( m_hAngle < 0.0 ) ? sin( horz_beta_angle ) : cos( horz_beta_angle ) ); + vert_add = nWidth * ( ( m_vAngle < 0.0 ) ? sin( vert_beta_angle ) : cos( vert_beta_angle ) ); + + // get absolute values for the distances + horz_add = fabs( horz_add ); + vert_add = fabs( vert_add ); + + // get new image size ( original size + distance ) + new_width = (int)horz_add + nWidth; + new_height = (int)vert_add + nHeight; + + // get scale factor for width and height + horz_factor = horz_add / new_height; + vert_factor = vert_add / new_width; + + // if horizontal angle is greater than zero... + // else, initial distance is equal to maximum distance ( in negative form ) + if( m_hAngle > 0.0 ) + { + // initial distance is zero and scale is negative ( to decrease ) + dx = 0; + horz_factor *= -1.0; + } + else + { + dx = -horz_add; + } + + // if vertical angle is greater than zero... + // else, initial distance is equal to maximum distance ( in negative form ) + if( m_vAngle > 0.0 ) + { + // initial distance is zero and scale is negative ( to decrease ) + dy = 0; + vert_factor *= -1.0; + } + else + { + dy = -vert_add; + } + + // allocates a new image with the new size + + bool sixteenBit = m_orgImage.sixteenBit(); + + m_destImage = Digikam::DImg(new_width, new_height, sixteenBit, m_orgImage.hasAlpha()); + m_destImage.fill( Digikam::DColor(m_backgroundColor.rgb(), sixteenBit) ); + + uchar *pResBits = m_destImage.bits(); + unsigned short *pResBits16 = (unsigned short *)m_destImage.bits(); + + Digikam::DImgImageFilters filters; + + for( y = 0; y < new_height; y++) + { + for( x = 0; x < new_width; x++, p += 4 ) + { + // get new positions + nx = x + dx + y * horz_factor; + ny = y + dy + x * vert_factor; + + // if is inside the source image + if (isInside (nWidth, nHeight, ROUND( nx ), ROUND( ny ))) + { + if( m_antiAlias ) + { + if (!sixteenBit) + filters.pixelAntiAliasing(pBits, nWidth, nHeight, nx, ny, + &pResBits[p+3], &pResBits[p+2], + &pResBits[p+1], &pResBits[p]); + else + filters.pixelAntiAliasing16(pBits16, nWidth, nHeight, nx, ny, + &pResBits16[p+3], &pResBits16[p+2], + &pResBits16[p+1], &pResBits16[p]); + } + else + { + pt = setPosition (nWidth, ROUND( nx ), ROUND( ny )); + + for (int z = 0 ; z < 4 ; z++) + { + if (!sixteenBit) + pResBits[p+z] = pBits[pt+z]; + else + pResBits16[p+z] = pBits16[pt+z]; + } + } + } + } + + // Update the progress bar in dialog. + progress = (int)(((double)y * 100.0) / new_height); + if (progress%5 == 0) + postProgress( progress ); + } + + // To compute the rotated destination image size using original image dimensions. + int W = (int)(fabs(m_orgH * ( ( m_hAngle < 0.0 ) ? sin( horz_beta_angle ) : cos( horz_beta_angle ))))+ + m_orgW; + int H = (int)(fabs(m_orgW * ( ( m_vAngle < 0.0 ) ? sin( vert_beta_angle ) : cos( vert_beta_angle ))))+ + m_orgH; + + m_newSize.setWidth(W); + m_newSize.setHeight(H); +} + +} // NameSpace DigikamShearToolImagesPlugin |