scanned-image-extractor/scannerExtract/copytargets.cpp

239 lines
7.3 KiB
C++

/***********************************************************************
* This file is part of Scanned Image Extract.
*
* Scanned Image Extract 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 3 of the License, or
* (at your option) any later version.
*
* Scanned Image Extract 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 Scanned Image Extract. If not, see <http://www.gnu.org/licenses/>
*
*
* Copyright (C) 2015, Dominik Rueß; info@dominik-ruess.de
**********************************************************************/
#include "copytargets.h"
#include <opencv/cv.h>
#ifndef OPENCV2
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#else
#include <opencv/highgui.h>
#endif
#include <QDir>
#include <QDebug>
#include "extracttargets.h"
QMutex CopyTargets::memorySaveMutex;
CopyTargets::CopyTargets(QObject *parent)
: QThread(parent)
, _stopped(false)
, _exitWritingOperationDone(false)
{
}
CopyTargets::~CopyTargets()
{
_fileListMutex.lock();
abortSaveFile(0);
while (!_exitWritingOperationDone || _filesToCopy.size() > 0)
{
_fileListMutex.unlock();
// saving may occur on closing
qDebug() << "waiting for all writing operations to finish (still" << _filesToCopy.size() << "to write)";
//_computationCondition.wait(&_computationRunning);
//qDebug() << "finished writing next image";
QThread::wait(500);
_fileListMutex.lock();
}
_filesToCopy.clear();
_fileListMutex.unlock();
//_computationRunning.unlock();
_stopped = true;
_condition.wakeAll();
wait();
}
void CopyTargets::addSaveFiles(SourceFilePtr source)
{
QMutexLocker l(&_fileListMutex);
_filesToCopy.push_back(source);
_abortSaveFile = 0;
if (!isRunning()) {
start(QThread::LowPriority);
} else {
_condition.wakeOne();
}
}
void CopyTargets::abortSaveFile(SourceFilePtr file)
{
_abortSaveFile = file;
}
void CopyTargets::clear()
{
QMutexLocker l(&_fileListMutex);
_filesToCopy.clear();
}
#define ABORT_CURRENT_TEST(breakit) \
if (_abortSaveFile.get() != 0 \
&& file->source.absoluteFilePath() == _abortSaveFile->source.absoluteFilePath()) \
{ \
if (breakit) break; \
else continue; \
}
void CopyTargets::run()
{
while (!_stopped) {
SourceFilePtr file;
{
QMutexLocker l(&_fileListMutex);
if (_filesToCopy.size() == 0) {
_condition.wait(&_fileListMutex);
// continue: in the meantime it might have been stopped
// or set empty
continue;
}
file= _filesToCopy.first();
_filesToCopy.pop_front();
}
//QMutexLocker l(&_computationRunning);
QMutexLocker l1(&ExtractTargets::imageMutex);
QList<TargetImagePtr> targets = file->targets;
QList<BackMapPtr> backmaps;
for (int i=0; i<targets.size(); i++)
{
backmaps.append(targets[i]->backmap);
}
l1.unlock();
QMutexLocker l2(&memorySaveMutex);
cv::Mat src = cv::imread(file->source.canonicalFilePath().toLocal8Bit().data(),
CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
QDir targetDir (QDir::rootPath());
targetDir.mkpath(QFileInfo(_targetDir).absolutePath());
for (int i=0; i<targets.size(); i++)
{
ABORT_CURRENT_TEST(true);
if (targets[i]->boundary->getCopied()) {
qDebug() << "Target " << i
<< " of source "
<< file->source.canonicalFilePath()
<< " has already been copied in this session, skipping";
continue;
}
if (targets[i]->copyId == -1)
{
targets[i]->copyId = ++TargetImage::nextCopyId;
}
const int tW = targets[i]->width;
const int tH = targets[i]->height;
if (tW == 0 || tH == 0) {
continue;
}
cv::Mat mapX(tH, tW, CV_32FC1),
mapY(tH, tW, CV_32FC1);
cv::Mat out(tH, tW, src.type());
for (int r=0; r<tH; r++) {
float* mX = mapX.ptr<float>(r);
float* mY = mapY.ptr<float>(r);
for (int c=0; c<tW; c++) {
backmaps[i]->transform(QPointF(c, r), mX[c], mY[c]);
}
ABORT_CURRENT_TEST(true);
}
ABORT_CURRENT_TEST(true);
cv::transpose(mapX, mapX);
cv::transpose(mapY, mapY);
ABORT_CURRENT_TEST(false);
cv::remap(src, out, mapX, mapY, CV_INTER_CUBIC);
mapX.release();
mapY.release();
cv::flip(out, out, 0);
QString newFileName(QString("%1%2%3_%4.%5")
.arg(_targetDir + QDir::separator())
.arg(_prefix)
.arg(file->source.baseName())
.arg(targets[i]->copyId, (int)FIELD_WIDTH, (int)10, QChar('0'))
.arg(file->source.suffix()));
cv::Mat out2;
int rot = targets[i]->determinedRotation + targets[i]->rotation + 1;
if (out.size().width ==0 || out.size().height == 0)
{
emit copyError(file, targets[i]);
}
else
{
switch(rot) {
case 1:
case 5:
case -3:
cv::transpose(out, out2);
cv::flip(out2, out2, 1);
break;
case 2:
case 6:
case -2:
cv::flip(out, out2, -1);
break;
case 3:
case -1:
cv::transpose(out, out2);
cv::flip(out2, out2, 0);
break;
default:
out2=out;
break;
}
if (cv::imwrite(newFileName.toLocal8Bit().data(), out2)) {
ABORT_CURRENT_TEST(true);
targets[i]->boundary->setCopied(true);
if (!_stopped)
{
emit copied(QFileInfo(newFileName).fileName(),
QFileInfo(newFileName).absolutePath());
}
} else {
if (!_stopped)
{
emit copyError(file, targets[i]);
}
}
}
}
ABORT_CURRENT_TEST(false);
file->changed = false;
src.release();
l2.unlock();
//l.unlock();
_computationCondition.wakeAll();
}
_computationCondition.wakeAll();
}