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.
kipi-plugins/kipi-plugins/jpeglossless/actionthread.cpp

238 lines
7.5 KiB

/* ============================================================
*
* This file is a part of kipi-plugins project
* http://www.kipi-plugins.org
*
* Date : 2003-12-03
* Description : a class to manage JPEGLossLess plugin
* actions using threads
*
* Copyright (C) 2003-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
* Copyright (C) 2004-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
* Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* NOTE: Do not use kdDebug() in this implementation because
* it will be multithreaded. Use tqDebug() instead.
* See B.K.O #133026 for details.
*
* 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.
*
* ============================================================ */
// TQt includes.
#include <tqapplication.h>
#include <tqdir.h>
#include <tqdeepcopy.h>
// KDE includes.
#include <kdebug.h>
// Local includes.
#include "utils.h"
#include "imagerotate.h"
#include "imageflip.h"
#include "convert2grayscale.h"
#include "actionthread.h"
namespace KIPIJPEGLossLessPlugin
{
ActionThread::ActionThread( KIPI::Interface* interface, TQObject *parent)
: TQThread(), m_parent(parent), m_interface( interface )
{
}
ActionThread::~ActionThread()
{
// cancel the thread
cancel();
// wait for the thread to finish
wait();
}
void ActionThread::rotate(const KURL::List& urlList, RotateAction val)
{
for (KURL::List::const_iterator it = urlList.begin();
it != urlList.end(); ++it )
{
KIPI::ImageInfo info = m_interface->info( *it );
/*
Removing this code:
- for JPEGs, jpegtransform is using the Exiv2Iface and matrix multiplication
to compute the mathematically correct rotation (taking flip operations into account,
the code below only angles). Metadata tag is reset.
- For ImageMagick, no metadata is taken into account, and no metadata is changed!
Angle from host application still applies.
// Don't use the host angle in case of auto-rotation (Rot0)
if (val != Rot0)
{
// If the image is being displayed rotaed in the host application, then rotate that
// angle too.
int angle = (info.angle() + 360) % 360;
// When the image has been rotated on the disk we can assume that it
// does not need to be rotated before being displayed.
info.setAngle( 0 );
if ( val == Rot90 )
angle += 90;
else if ( val == Rot180 )
angle += 180;
else if ( val == Rot270 )
angle += 270;
angle = (angle+360) % 360;
if ( (90-45) <= angle && angle < (90+45) )
val = Rot90;
else if ( (180-45) <= angle && angle < (180+45) )
val = Rot180;
else if ( (270-45) <= angle && angle < (270+45) )
val = Rot270;
else
val = Rot0;
}
*/
Task *t = new Task;
t->filePath = TQDeepCopy<TQString>((*it).path()); //deep copy
t->action = Rotate;
t->rotAction = val;
m_taskQueue.enqueue(t);
}
}
void ActionThread::flip(const KURL::List& urlList, FlipAction val)
{
for (KURL::List::const_iterator it = urlList.begin();
it != urlList.end(); ++it )
{
KIPI::ImageInfo info = m_interface->info( *it );
int angle = (info.angle() + 360) % 360;
if ( ((90-45) <= angle && angle < (90+45)) || ((270-45) < angle && angle < (270+45)) )
{
// The image is rotated 90 or 270 degrees, which means that the flip operations
// must be switched to gain the effect the user expects.
// Note: this will only work if the angles is one of 90,180,270.
val = (FlipAction) !val;
}
Task *t = new Task;
t->filePath = TQDeepCopy<TQString>((*it).path()); //deep copy
t->action = Flip;
t->flipAction = val;
m_taskQueue.enqueue(t);
}
}
void ActionThread::convert2grayscale(const KURL::List& urlList)
{
for (KURL::List::const_iterator it = urlList.begin();
it != urlList.end(); ++it )
{
Task *t = new Task;
t->filePath = TQDeepCopy<TQString>((*it).path()); //deep copy
t->action = GrayScale;
m_taskQueue.enqueue(t);
}
}
void ActionThread::cancel()
{
m_taskQueue.flush();
}
void ActionThread::run()
{
while (!m_taskQueue.isEmpty())
{
Task *t = m_taskQueue.dequeue();
if (!t) continue;
TQString errString;
EventData *d = new EventData;
switch (t->action)
{
case Rotate :
{
d->action = Rotate;
d->fileName = t->filePath;
d->starting = true;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, d));
bool result = true;
ImageRotate imageRotate;
result = imageRotate.rotate(t->filePath, t->rotAction, errString);
EventData *r = new EventData;
r->action = Rotate;
r->fileName = t->filePath;
r->success = result;
r->errString = errString;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, r));
break;
}
case Flip:
{
d->action = Flip;
d->fileName = t->filePath;
d->starting = true;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, d));
ImageFlip imageFlip;
bool result = imageFlip.flip(t->filePath, t->flipAction, errString);
EventData *r = new EventData;
r->action = Flip;
r->fileName = t->filePath;
r->success = result;
r->errString = errString;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, r));
break;
}
case GrayScale:
{
d->action = GrayScale;
d->fileName = t->filePath;
d->starting = true;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, d));
ImageGrayScale imageGrayScale;
bool result = imageGrayScale.image2GrayScale(t->filePath, errString);
EventData *r = new EventData;
r->action = GrayScale;
r->fileName = t->filePath;
r->success = result;
r->errString = errString;
TQApplication::postEvent(m_parent, new TQCustomEvent(TQEvent::User, r));
break;
}
default:
{
tqDebug("KIPIJPEGLossLessPlugin:ActionThread: "
"Unknown action specified");
delete d;
}
}
delete t;
}
}
} // NameSpace KIPIJPEGLossLessPlugin