diff options
Diffstat (limited to 'src/libs/widgets/imageplugins/imageregionwidget.cpp')
| -rw-r--r-- | src/libs/widgets/imageplugins/imageregionwidget.cpp | 473 | 
1 files changed, 473 insertions, 0 deletions
| diff --git a/src/libs/widgets/imageplugins/imageregionwidget.cpp b/src/libs/widgets/imageplugins/imageregionwidget.cpp new file mode 100644 index 00000000..c1392cc2 --- /dev/null +++ b/src/libs/widgets/imageplugins/imageregionwidget.cpp @@ -0,0 +1,473 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + *  + * Date        : 2004-08-17 + * Description : a widget to draw an image clip region. + *  + * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles 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. + *  + * ============================================================ */ + +// C++ includes. + +#include <cmath> + +// TQt includes. + +#include <tqpainter.h> +#include <tqpixmap.h> +#include <tqtimer.h> +#include <tqpainter.h> +#include <tqpen.h> +#include <tqimage.h> +#include <tqbrush.h> +#include <tqfont.h>  +#include <tqfontmetrics.h>  +#include <tqpointarray.h> + +// KDE includes. + +#include <kstandarddirs.h> +#include <kcursor.h> +#include <tdeglobal.h> +#include <tdeapplication.h> + +// Local includes. + +#include "ddebug.h" +#include "imageiface.h" +#include "imageregionwidget.h" +#include "imageregionwidget.moc" + +namespace Digikam +{ + +class ImageRegionWidgetPriv +{ + +public: + +    ImageRegionWidgetPriv() +    { +        iface        = 0; +        separateView = ImageRegionWidget::SeparateViewVertical; +    } + +    int          separateView; +    int          xpos; +    int          ypos; + +    TQPixmap      pixmapRegion;          // Pixmap of current region to render. +     +    TQPointArray  hightlightPoints; +     +    DImg         image;                 // Entire content image to render pixmap. +     +    ImageIface  *iface; +}; + +ImageRegionWidget::ImageRegionWidget(int wp, int hp, TQWidget *parent, bool scrollBar) +                 : PreviewWidget(parent) +{ +    d = new ImageRegionWidgetPriv; +    d->iface = new ImageIface(0, 0); +    d->image = d->iface->getOriginalImg()->copy();  + +    setMinimumSize(wp, hp); +    setBackgroundColor(colorGroup().background()); + +    if( !scrollBar )  +    { +       setVScrollBarMode( TQScrollView::AlwaysOff ); +       setHScrollBarMode( TQScrollView::AlwaysOff ); +    } +     +    connect(this, TQ_SIGNAL(signalZoomFactorChanged(double)), +            this, TQ_SLOT(slotZoomFactorChanged())); +} + +ImageRegionWidget::~ImageRegionWidget() +{ +    if (d->iface) delete d->iface; +    delete d; +} + +void ImageRegionWidget::resizeEvent(TQResizeEvent* e) +{ +    if (!e) return; + +    TQScrollView::resizeEvent(e); + +    // NOTE: We will always adapt the min. zoom factor to the visible size of canvas +  +    double srcWidth  = previewWidth(); +    double srcHeight = previewHeight(); +    double dstWidth  = contentsRect().width(); +    double dstHeight = contentsRect().height(); +    double zoom      = TQMAX(dstWidth/srcWidth, dstHeight/srcHeight);  + +    setZoomMin(zoom); +    setZoomMax(zoom*12.0); +    setZoomFactor(zoom); +} + +int ImageRegionWidget::previewWidth() +{ +    return d->image.width(); +} + +int ImageRegionWidget::previewHeight() +{ +    return d->image.height(); +} + +bool ImageRegionWidget::previewIsNull() +{ +    return d->image.isNull(); +} + +void ImageRegionWidget::resetPreview() +{ +    d->image.reset(); +} + +void ImageRegionWidget::paintPreview(TQPixmap *pix, int sx, int sy, int sw, int sh) +{ +    DImg img = d->image.smoothScaleSection(sx, sy, sw, sh, tileSize(), tileSize());     +    TQPixmap pix2 = d->iface->convertToPixmap(img); +    bitBlt(pix, 0, 0, &pix2, 0, 0); +} + +void ImageRegionWidget::setHighLightPoints(const TQPointArray& pointsList) +{ +    d->hightlightPoints = pointsList; +    repaintContents(false);    +} + +void ImageRegionWidget::slotZoomFactorChanged() +{ +    emit signalContentsMovedEvent(true); +} + +void ImageRegionWidget::slotSeparateViewToggled(int mode) +{ +    d->separateView = mode; +    updateContentsSize(); +    slotZoomFactorChanged();  +} + +TQRect ImageRegionWidget::getImageRegion() +{ +    TQRect region;     + +    switch (d->separateView) +    { +        case SeparateViewVertical: +        case SeparateViewHorizontal: +        case SeparateViewNone: +            region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());  +            break; +        case SeparateViewDuplicateVert: +            region = TQRect(contentsX(), contentsY(), visibleWidth()/2, visibleHeight());   +            break; +        case SeparateViewDuplicateHorz: +            region = TQRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()/2);   +            break; +    } +         +    return region;    +} + +void ImageRegionWidget::viewportPaintExtraData() +{    +    if (!m_movingInProgress && !d->pixmapRegion.isNull()) +    { +        TQPainter p(viewport()); +        TQRect region = getLocalTargetImageRegion(); +        TQRect rt(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));  + +        region = getLocalImageRegionToRender(); +        TQRect ro(contentsToViewport(region.topLeft()), contentsToViewport(region.bottomRight()));  + +        bitBlt(viewport(), rt.x(), rt.y(), &d->pixmapRegion, 0, 0, rt.width(), rt.height()); + +        // Drawing separate view. +         +        switch (d->separateView) +        { +            case SeparateViewVertical: +            case SeparateViewDuplicateVert: +            { +                p.setPen(TQPen(TQt::white, 2, TQt::SolidLine)); +                p.drawLine(rt.topLeft().x(),    rt.topLeft().y(), +                           rt.bottomLeft().x(), rt.bottomLeft().y()); +                p.setPen(TQPen(TQt::red, 2, TQt::DotLine)); +                p.drawLine(rt.topLeft().x(),    rt.topLeft().y()+1, +                           rt.bottomLeft().x(), rt.bottomLeft().y()-1); +                             +                p.setPen(TQPen(TQt::red, 1)) ;                     +                TQFontMetrics fontMt = p.fontMetrics(); +                 +                TQString text(i18n("Target")); +                TQRect textRect; +                TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);  +                textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().y()+20)); +                textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) ); +                p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) ); +                p.drawRect(textRect); +                p.drawText(textRect, TQt::AlignCenter, text); +                             +                text = i18n("Original");                     +                fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);  + +                if (d->separateView == SeparateViewVertical) +                    ro.moveBy(-ro.width(), 0); + +                textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().y()+20)); +                textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );        +                p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) ); +                p.drawRect(textRect); +                p.drawText(textRect, TQt::AlignCenter, text); +                break; +            } +            case SeparateViewHorizontal: +            case SeparateViewDuplicateHorz: +            { +                p.setPen(TQPen(TQt::white, 2, TQt::SolidLine)); +                p.drawLine(rt.topLeft().x()+1,  rt.topLeft().y(), +                           rt.topRight().x()-1, rt.topRight().y()); +                p.setPen(TQPen(TQt::red, 2, TQt::DotLine)); +                p.drawLine(rt.topLeft().x(),   rt.topLeft().y(), +                           rt.topRight().x(), rt.topRight().y()); +                             +                p.setPen(TQPen(TQt::red, 1)) ;                     +                TQFontMetrics fontMt = p.fontMetrics(); +                 +                TQString text(i18n("Target")); +                TQRect textRect; +                TQRect fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text);  +                textRect.setTopLeft(TQPoint(rt.topLeft().x()+20, rt.topLeft().y()+20)); +                textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2) ); +                p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) ); +                p.drawRect(textRect); +                p.drawText(textRect, TQt::AlignCenter, text); +                             +                text = i18n("Original");                     +                fontRect = fontMt.boundingRect(0, 0, contentsWidth(), contentsHeight(), 0, text); + +                if (d->separateView == SeparateViewHorizontal) +                    ro.moveBy(0, -ro.height()); + +                textRect.setTopLeft(TQPoint(ro.topLeft().x()+20, ro.topLeft().y()+20)); +                textRect.setSize( TQSize(fontRect.width()+2, fontRect.height()+2 ) );        +                p.fillRect(textRect, TQBrush(TQColor(250, 250, 255)) ); +                p.drawRect(textRect); +                p.drawText(textRect, TQt::AlignCenter, text); +                break; +            } +        } +         +        // Drawing HighLighted points. +         +        if (!d->hightlightPoints.isEmpty()) +        { +            TQPoint pt; +            TQRect  hpArea; +             +            for (int i = 0 ; i < d->hightlightPoints.count() ; i++) +            { +                pt = d->hightlightPoints.point(i); +                 +                if ( getImageRegionToRender().contains(pt) ) +                { +                    int x = (int)(((double)pt.x() * tileSize()) / floor(tileSize() / zoomFactor())); +                    int y = (int)(((double)pt.y() * tileSize()) / floor(tileSize() / zoomFactor())); + +                    TQPoint hp(contentsToViewport(TQPoint(x, y))); +                    hpArea.setSize(TQSize((int)(16*zoomFactor()), (int)(16*zoomFactor()))); +                    hpArea.moveCenter(hp); + +                    p.setPen(TQPen(TQt::white, 2, TQt::SolidLine)); +                    p.drawLine(hp.x(), hpArea.y(),  +                               hp.x(), hp.y()-(int)(3*zoomFactor())); +                    p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),  +                               hp.x(), hpArea.bottom()); +                    p.drawLine(hpArea.x(),                   hp.y(),  +                               hp.x()-(int)(3*zoomFactor()), hp.y()); +                    p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),  +                               hpArea.right(),                hp.y()); + +                    p.setPen(TQPen(TQt::red, 2, TQt::DotLine)); +                    p.drawLine(hp.x(), hpArea.y(),  +                               hp.x(), hp.y()-(int)(3*zoomFactor())); +                    p.drawLine(hp.x(), hp.y()+(int)(3*zoomFactor()),  +                               hp.x(), hpArea.bottom()); +                    p.drawLine(hpArea.x(),                   hp.y(),  +                               hp.x()-(int)(3*zoomFactor()), hp.y()); +                    p.drawLine(hp.x()+(int)(3*zoomFactor()), hp.y(),  +                               hpArea.right(),                hp.y()); +                } +            } +        } +        p.end(); +    } +} + +void ImageRegionWidget::setCenterContentsPosition() +{ +    center(contentsWidth()/2, contentsHeight()/2);     +    slotZoomFactorChanged(); +} + +void ImageRegionWidget::setContentsPosition(int x, int y, bool targetDone) +{ +    if( targetDone ) +        m_movingInProgress = false; + +    setContentsPos(x, y);     +     +    if( targetDone ) +       slotZoomFactorChanged(); +} + +void ImageRegionWidget::backupPixmapRegion() +{ +    d->pixmapRegion = TQPixmap(); +} + +void ImageRegionWidget::restorePixmapRegion() +{ +    m_movingInProgress = true; +    viewport()->repaint(false); +} + +void ImageRegionWidget::updatePreviewImage(DImg *img) +{ +    DImg image = img->copy(); +    TQRect r    = getLocalImageRegionToRender(); +    image.resize(r.width(), r.height()); + +    // Because image plugins are tool witch only work on image data, the DImg container +    // do not contain metadata from original image. About Color Managed View, we need to  +    // restore the embedded ICC color profile.  +    image.setICCProfil(d->image.getICCProfil()); +    d->pixmapRegion = d->iface->convertToPixmap(image); +} + +DImg ImageRegionWidget::getImageRegionImage() +{ +    return (d->image.copy(getImageRegionToRender())); +} + +TQRect ImageRegionWidget::getImageRegionToRender() +{ +    TQRect r = getLocalImageRegionToRender(); + +    int x = (int)(((double)r.x()      / tileSize()) * floor(tileSize() / zoomFactor())); +    int y = (int)(((double)r.y()      / tileSize()) * floor(tileSize() / zoomFactor())); +    int w = (int)(((double)r.width()  / tileSize()) * floor(tileSize() / zoomFactor()));    +    int h = (int)(((double)r.height() / tileSize()) * floor(tileSize() / zoomFactor())); + +    TQRect rect(x, y, w, h); +    return (rect); +} + +TQRect ImageRegionWidget::getLocalImageRegionToRender() +{ +    TQRect region; +     +    if (d->separateView == SeparateViewVertical) +    { +        region = TQRect((int)ceilf(contentsX()+visibleWidth()/2.0), contentsY(),  +                       (int)ceilf(visibleWidth()/2.0),             visibleHeight()); +    } +    else if (d->separateView == SeparateViewHorizontal) +    { +        region = TQRect(contentsX(),    (int)ceilf(contentsY()+visibleHeight()/2.0),  +                       visibleWidth(), (int)ceilf(visibleHeight()/2.0)); +    } +    else if (d->separateView == SeparateViewDuplicateVert) +    { +        region = TQRect(contentsX(),                    contentsY(),  +                       (int)ceilf(visibleWidth()/2.0), visibleHeight()); +    } +    else if (d->separateView == SeparateViewDuplicateHorz) +    { +        region = TQRect(contentsX(),    contentsY(),  +                       visibleWidth(), (int)ceilf(visibleHeight()/2.0)); +    } +    else  +    { +        region = TQRect(contentsX(),    contentsY(),  +                       visibleWidth(), visibleHeight()); +    } +     +    return (region); +} + +TQRect ImageRegionWidget::getLocalTargetImageRegion() +{ +    TQRect region = getLocalImageRegionToRender(); +     +    if (d->separateView == SeparateViewDuplicateVert) +        region.moveBy(region.width(), 0); +    else if (d->separateView == SeparateViewDuplicateHorz) +        region.moveBy(0, region.height()); +     +    return region; +} + +void ImageRegionWidget::setContentsSize() +{ +    switch (d->separateView) +    { +        case SeparateViewVertical: +        case SeparateViewHorizontal: +        case SeparateViewNone: +        { +            PreviewWidget::setContentsSize(); +            break; +        } +        case SeparateViewDuplicateVert: +        { +            resizeContents(zoomWidth()+visibleWidth()/2, zoomHeight()); +            break; +        } +        case SeparateViewDuplicateHorz: +        { +            resizeContents(zoomWidth(), zoomHeight()+visibleHeight()/2); +            break; +        } +        default: +            DWarning() << "Unknown separation view specified" << endl; +    } +} + +void ImageRegionWidget::contentsWheelEvent(TQWheelEvent *e) +{ +    e->accept(); + +    if (e->state() & TQt::ControlButton) +    { +        if (e->delta() < 0 && !maxZoom()) +            slotIncreaseZoom(); +        else if (e->delta() > 0 && !minZoom()) +            slotDecreaseZoom(); +        return; +    } +} + +}  // NameSpace Digikam | 
