Beispiel #1
0
void ShearFilter::filterImage()
{
    int          progress;
    register 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 = reinterpret_cast<unsigned short*>(m_orgImage.bits());

    // get beta ( complementary ) angle for horizontal and vertical angles
    horz_beta_angle = (((d->hAngle < 0.0) ? 180.0 : 90.0) - d->hAngle) * DEG2RAD;
    vert_beta_angle = (((d->vAngle < 0.0) ? 180.0 : 90.0) - d->vAngle) * DEG2RAD;

    // get new distance for width and height values
    horz_add = nHeight * ((d->hAngle < 0.0) ? sin(horz_beta_angle) : cos(horz_beta_angle));
    vert_add = nWidth  * ((d->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 (d->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 (d->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     = DImg(new_width, new_height, sixteenBit, m_orgImage.hasAlpha());
    m_destImage.fill(DColor(d->backgroundColor.rgb(), sixteenBit));

    uchar* pResBits            = m_destImage.bits();
    unsigned short* pResBits16 = reinterpret_cast<unsigned short*>(m_destImage.bits());

    PixelsAliasFilter alias;

    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, lround(nx), lround(ny)))
            {
                if (d->antiAlias)
                {
                    if (!sixteenBit)
                        alias.pixelAntiAliasing(pBits, nWidth, nHeight, nx, ny,
                                                &pResBits[p + 3], &pResBits[p + 2],
                                                &pResBits[p + 1], &pResBits[p]);
                    else
                        alias.pixelAntiAliasing16(pBits16, nWidth, nHeight, nx, ny,
                                                  &pResBits16[p + 3], &pResBits16[p + 2],
                                                  &pResBits16[p + 1], &pResBits16[p]);
                }
                else
                {
                    pt = setPosition(nWidth, lround(nx), lround(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(d->orgH * ((d->hAngle < 0.0) ? sin(horz_beta_angle) : cos(horz_beta_angle)))) + d->orgW;
    int H = (int)(fabs(d->orgW * ((d->vAngle < 0.0) ? sin(vert_beta_angle) : cos(vert_beta_angle)))) + d->orgH;

    d->newSize.setWidth(W);
    d->newSize.setHeight(H);
}
Beispiel #2
0
void FreeRotationFilter::filterImage()
{
    int          progress;
    register int w, h, nw, nh, j, i = 0;
    int          nNewHeight, nNewWidth;
    int          nhdx, nhdy, nhsx, nhsy;
    double       lfSin, lfCos, lfx, lfy;

    int nWidth  = m_orgImage.width();
    int nHeight = m_orgImage.height();

    uchar* pBits            = m_orgImage.bits();
    unsigned short* pBits16 = (unsigned short*)m_orgImage.bits();

    // first of all, we need to calculate the sin and cos of the given angle

    lfSin = sin(d->settings.angle * -d->DEG2RAD);
    lfCos = cos(d->settings.angle * -d->DEG2RAD);

    // now, we have to calc the new size for the destination image

    if ((lfSin * lfCos) < 0)
    {
        nNewWidth  = lround (fabs (nWidth * lfCos - nHeight * lfSin));
        nNewHeight = lround (fabs (nWidth * lfSin - nHeight * lfCos));
    }
    else
    {
        nNewWidth  = lround (fabs (nWidth * lfCos + nHeight * lfSin));
        nNewHeight = lround (fabs (nWidth * lfSin + nHeight * lfCos));
    }

    // getting the destination's center position

    nhdx = nNewWidth  / 2;
    nhdy = nNewHeight / 2;

    // getting the source's center position

    nhsx = nWidth  / 2;
    nhsy = nHeight / 2;

    // now, we have to alloc a new image

    bool sixteenBit = m_orgImage.sixteenBit();
    m_destImage     = DImg(nNewWidth, nNewHeight, sixteenBit, m_orgImage.hasAlpha());

    if (m_destImage.isNull())
    {
        return;
    }

    m_destImage.fill( DColor(d->settings.backgroundColor.rgb(), sixteenBit) );

    uchar* pResBits            = m_destImage.bits();
    unsigned short* pResBits16 = (unsigned short*)m_destImage.bits();

    PixelsAliasFilter alias;

    // main loop

    for (h = 0; runningFlag() && (h < nNewHeight); ++h)
    {
        nh = h - nhdy;

        for (w = 0; runningFlag() && (w < nNewWidth); ++w)
        {
            nw = w - nhdx;

            i = setPosition (nNewWidth, w, h);

            lfx = (double)nw * lfCos - (double)nh * lfSin + nhsx;
            lfy = (double)nw * lfSin + (double)nh * lfCos + nhsy;

            if (isInside (nWidth, nHeight, (int)lfx, (int)lfy))
            {
                if (d->settings.antiAlias)
                {
                    if (!sixteenBit)
                        alias.pixelAntiAliasing(pBits, nWidth, nHeight, lfx, lfy,
                                                &pResBits[i+3], &pResBits[i+2],
                                                &pResBits[i+1], &pResBits[i]);
                    else
                        alias.pixelAntiAliasing16(pBits16, nWidth, nHeight, lfx, lfy,
                                                  &pResBits16[i+3], &pResBits16[i+2],
                                                  &pResBits16[i+1], &pResBits16[i]);
                }
                else
                {
                    j = setPosition (nWidth, (int)lfx, (int)lfy);

                    for (int p = 0 ; p < 4 ; ++p)
                    {
                        if (!sixteenBit)
                        {
                            pResBits[i] = pBits[j];
                        }
                        else
                        {
                            pResBits16[i] = pBits16[j];
                        }

                        ++i;
                        ++j;
                    }
                }
            }
        }

        // Update the progress bar in dialog.
        progress = (int) (((double) h * 100.0) / nNewHeight);

        if (progress % 5 == 0)
        {
            postProgress(progress);
        }
    }

    // Compute the rotated destination image size using original image dimensions.
    int    W, H;
    double absAngle = fabs(d->settings.angle);

    // stop here when no angle was set
    if (absAngle == 0.0)
    {
        return;
    }

    if (absAngle < 90.0)
    {
        W = (int)(d->settings.orgW * cos(absAngle * d->DEG2RAD) + d->settings.orgH * sin(absAngle * d->DEG2RAD));
        H = (int)(d->settings.orgH * cos(absAngle * d->DEG2RAD) + d->settings.orgW * sin(absAngle * d->DEG2RAD));
    }
    else
    {
        H = (int)(d->settings.orgW * cos((absAngle-90.0) * d->DEG2RAD) + d->settings.orgH * sin((absAngle-90.0) * d->DEG2RAD));
        W = (int)(d->settings.orgH * cos((absAngle-90.0) * d->DEG2RAD) + d->settings.orgW * sin((absAngle-90.0) * d->DEG2RAD));
    }

    // Auto-cropping destination image without black holes around.
    QRect autoCrop;

    switch (d->settings.autoCrop)
    {
        case FreeRotationContainer::WidestArea:
        {
            // 'Widest Area' method (by Renchi Raju).

            autoCrop.setX((int) (nHeight * sin(absAngle * d->DEG2RAD)));
            autoCrop.setY((int) (nWidth  * sin(absAngle * d->DEG2RAD)));
            autoCrop.setWidth((int)  (nNewWidth  - 2* nHeight * sin(absAngle * d->DEG2RAD)));
            autoCrop.setHeight((int) (nNewHeight - 2* nWidth  * sin(absAngle * d->DEG2RAD)));

            if (!autoCrop.isValid())
            {
                m_destImage = DImg(m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit(),
                                   m_orgImage.hasAlpha());
                m_destImage.fill(DColor(d->settings.backgroundColor.rgb(), sixteenBit));
                d->settings.newSize   = QSize();
            }
            else
            {
                m_destImage = m_destImage.copy(autoCrop);
                d->settings.newSize.setWidth((int)  (W - 2* d->settings.orgH * sin(absAngle * d->DEG2RAD)));
                d->settings.newSize.setHeight((int) (H - 2* d->settings.orgW * sin(absAngle * d->DEG2RAD)));
            }

            break;
        }

        case FreeRotationContainer::LargestArea:
        {
            // 'Largest Area' method (by Gerhard Kulzer).

            float gamma = 0.0f;

            if (nHeight > nWidth)
            {
                gamma = atan((float) nWidth / (float) nHeight);

                if (absAngle < 90.0)
                {
                    autoCrop.setHeight((int) ((float) nWidth / cos(absAngle * d->DEG2RAD) / (tan(gamma) +
                                              tan(absAngle * d->DEG2RAD))));
                    autoCrop.setWidth((int) ((float) autoCrop.height() * tan(gamma)));
                }
                else
                {
                    autoCrop.setWidth((int) ((float) nWidth / cos((absAngle - 90.0) * d->DEG2RAD) / (tan(gamma) +
                                             tan((absAngle - 90.0) * d->DEG2RAD))));
                    autoCrop.setHeight((int) ((float) autoCrop.width() * tan(gamma)));
                }
            }
            else
            {
                gamma = atan((float) nHeight / (float) nWidth);

                if (absAngle < 90.0)
                {
                    autoCrop.setWidth((int) ((float) nHeight / cos(absAngle * d->DEG2RAD) / (tan(gamma) +
                                             tan(absAngle * d->DEG2RAD))));
                    autoCrop.setHeight((int) ((float) autoCrop.width() * tan(gamma)));
                }
                else
                {
                    autoCrop.setHeight((int) ((float) nHeight / cos((absAngle - 90.0) * d->DEG2RAD) /
                                              (tan(gamma) + tan((absAngle - 90.0) * d->DEG2RAD))));
                    autoCrop.setWidth((int) ((float) autoCrop.height() * tan(gamma)));
                }
            }

            autoCrop.moveCenter(QPoint(nNewWidth / 2, nNewHeight / 2));

            if (!autoCrop.isValid())
            {
                m_destImage = DImg(m_orgImage.width(), m_orgImage.height(), m_orgImage.sixteenBit(),
                                   m_orgImage.hasAlpha());
                m_destImage.fill(DColor(d->settings.backgroundColor.rgb(), sixteenBit));
                d->settings.newSize   = QSize();
            }
            else
            {
                m_destImage = m_destImage.copy(autoCrop);
                gamma       = atan((float) d->settings.orgH / (float) d->settings.orgW);

                if (absAngle < 90.0)
                {
                    d->settings.newSize.setWidth((int) ((float) d->settings.orgH / cos(absAngle * d->DEG2RAD) / (tan(gamma) +
                                                        tan(absAngle * d->DEG2RAD))));
                    d->settings.newSize.setHeight((int) ((float) d->settings.newSize.width() * tan(gamma)));
                }
                else
                {
                    d->settings.newSize.setHeight((int) ((float) d->settings.orgH / cos((absAngle - 90.0) * d->DEG2RAD) /
                                                         (tan(gamma) + tan((absAngle - 90.0) * d->DEG2RAD))));
                    d->settings.newSize.setWidth((int) ((float) d->settings.newSize.height() * tan(gamma)));
                }
            }

            break;
        }

        default: // No auto cropping.
        {
            d->settings.newSize.setWidth(W);
            d->settings.newSize.setHeight(H);
            break;
        }
    }
}