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.
205 lines
5.6 KiB
205 lines
5.6 KiB
/*
|
|
* copyright (c) 2004, 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.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 of the license, 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.
|
|
*
|
|
* you should have received a copy of the gnu general public license
|
|
* along with this program; if not, write to the free software
|
|
* foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
|
|
*/
|
|
|
|
#ifndef KIS_SCALE_VISITOR_H_
|
|
#define KIS_SCALE_VISITOR_H_
|
|
|
|
#include "tdelocale.h"
|
|
|
|
#include "kis_progress_subject.h"
|
|
#include "kis_progress_display_interface.h"
|
|
#include "kis_thread.h"
|
|
#include "kis_layer_visitor.h"
|
|
#include "kis_types.h"
|
|
#include "kis_layer.h"
|
|
#include "kis_group_layer.h"
|
|
#include "kis_paint_layer.h"
|
|
#include "kis_adjustment_layer.h"
|
|
#include "kis_transaction.h"
|
|
#include "kis_undo_adapter.h"
|
|
#include "kis_selection.h"
|
|
|
|
class KisProgressDisplayInterface;
|
|
class KisFilterStrategy;
|
|
|
|
class KisScaleWorker : public KisThread {
|
|
|
|
/* Structs for the image rescaling routine */
|
|
class Contrib {
|
|
public:
|
|
TQ_INT32 m_pixel;
|
|
double m_weight;
|
|
};
|
|
|
|
class ContribList {
|
|
public:
|
|
TQ_INT32 n; //number of contributors
|
|
Contrib *p; //pointer to list of contributions
|
|
};
|
|
|
|
public:
|
|
|
|
KisScaleWorker(KisPaintDevice * dev, double sx, double sy,
|
|
KisFilterStrategy *filterStrategy)
|
|
: KisThread()
|
|
, m_dev(dev)
|
|
, m_sx(sx)
|
|
, m_sy(sy)
|
|
, m_filterStrategy(filterStrategy) {};
|
|
|
|
virtual ~KisScaleWorker() {};
|
|
|
|
void run();
|
|
|
|
private:
|
|
TQ_INT32 m_pixelSize;
|
|
KisPaintDevice * m_dev;
|
|
double m_sx, m_sy;
|
|
KisFilterStrategy * m_filterStrategy;
|
|
|
|
|
|
/**
|
|
* calc_x_contrib()
|
|
*
|
|
* Calculates the filter weights for a single target column.
|
|
* contribX->p must be freed afterwards.
|
|
*
|
|
* Returns -1 if error, 0 otherwise.
|
|
*/
|
|
int calcContrib(ContribList *contribX, double cale, double fwidth, int srcwidth, KisFilterStrategy *filterStrategy, TQ_INT32 i);
|
|
|
|
ContribList * contrib; //array of contribution lists
|
|
|
|
|
|
};
|
|
|
|
|
|
class KisScaleVisitor : public KisLayerVisitor, KisProgressSubject {
|
|
|
|
public:
|
|
|
|
KisScaleVisitor(KisImageSP img,
|
|
double sx,
|
|
double sy,
|
|
KisProgressDisplayInterface *progress,
|
|
KisFilterStrategy *filterStrategy)
|
|
: KisLayerVisitor()
|
|
, m_img(img)
|
|
, m_sx(sx)
|
|
, m_sy(sy)
|
|
, m_progress(progress)
|
|
, m_filterStrategy(filterStrategy)
|
|
{
|
|
if ( progress )
|
|
progress -> setSubject(this, true, true);
|
|
emit notifyProgressStage(i18n("Scaling..."),0);
|
|
}
|
|
|
|
virtual ~KisScaleVisitor()
|
|
{
|
|
// Wait for all threads to finish
|
|
KisThread * t;
|
|
int threadcount = m_scalethreads.count();
|
|
int i = 0;
|
|
for ( t = m_scalethreads.first(); t; t = m_scalethreads.next()) {
|
|
//progress info
|
|
if (t) t->wait();
|
|
emit notifyProgress((100 / threadcount) * i);
|
|
++i;
|
|
|
|
}
|
|
emit notifyProgressDone();
|
|
// Delete all threads
|
|
m_scalethreads.setAutoDelete(true);
|
|
m_scalethreads.clear();
|
|
}
|
|
|
|
bool visit(KisPaintLayer *layer)
|
|
{
|
|
// XXX: If all is well, then the image's undoadapter will have started a macro for us
|
|
// This will break in a more multi-threaded environment
|
|
if (m_img->undoAdapter() && m_img->undoAdapter()->undo()) {
|
|
KisTransaction * cmd = new KisTransaction("", layer->paintDevice());
|
|
m_img->undoAdapter()->addCommand(cmd);
|
|
}
|
|
|
|
KisScaleWorker * scaleThread = new KisScaleWorker(layer->paintDevice(),
|
|
m_sx, m_sy, m_filterStrategy);
|
|
m_scalethreads.append(scaleThread);
|
|
scaleThread->start();
|
|
//scaleThread->run();
|
|
layer->setDirty();
|
|
return true;
|
|
}
|
|
|
|
bool visit(KisGroupLayer *layer)
|
|
{
|
|
//KisScaleVisitor visitor (m_img, m_sx, m_sy, m_progress, m_filterStrategy);
|
|
|
|
// XXX: Maybe faster to scale the projection and do something clever to avoid
|
|
// recompositing everything?
|
|
layer->resetProjection();
|
|
|
|
|
|
KisLayerSP child = layer->firstChild();
|
|
while (child) {
|
|
child->accept(*this);
|
|
child = child->nextSibling();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool visit(KisPartLayer */*layer*/)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual bool visit(KisAdjustmentLayer* layer)
|
|
{
|
|
KisThread * scaleThread = new KisScaleWorker(layer->selection().data(), m_sx, m_sy, m_filterStrategy);
|
|
m_scalethreads.append(scaleThread);
|
|
scaleThread->start();
|
|
layer->resetCache();
|
|
layer->setDirty();
|
|
return true;
|
|
}
|
|
|
|
|
|
// Implement KisProgressSubject
|
|
virtual void cancel()
|
|
{
|
|
KisThread * t;
|
|
for ( t = m_scalethreads.first(); t; t = m_scalethreads.next()) {
|
|
t->cancel();
|
|
}
|
|
}
|
|
|
|
|
|
private:
|
|
|
|
TQPtrList<KisThread> m_scalethreads;
|
|
KisImageSP m_img;
|
|
double m_sx;
|
|
double m_sy;
|
|
KisProgressDisplayInterface * m_progress;
|
|
KisFilterStrategy * m_filterStrategy;
|
|
};
|
|
|
|
#endif // KIS_SCALE_VISITOR_H_
|