388 lines
14 KiB
C++
388 lines
14 KiB
C++
/*******************************************************************************
|
|
#
|
|
# Copyright (C) 2010-2013 Matteo Paonessa <matteo.paonessa@gmail.com>
|
|
#
|
|
# This file is part of the Caesium distribution.
|
|
#
|
|
# Caesium 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.
|
|
#
|
|
# Caesium 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 Caesium; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
|
#
|
|
# Author: Matteo Paonessa <matteo.paonessa@gmail.com>
|
|
#
|
|
# ******************************************************************************/
|
|
|
|
#include "compressionthread.h"
|
|
#include "caesium.h"
|
|
#include "ui_caesium.h"
|
|
#include "global.h"
|
|
#include "imageresize.h"
|
|
|
|
#include <QSettings>
|
|
#include <QFile>
|
|
#include <QMessageBox>
|
|
#include <QDebug>
|
|
#include <QProgressDialog>
|
|
#include <QFileInfo>
|
|
#include <QDir>
|
|
|
|
#include <windows.h>
|
|
#include <afxres.h>
|
|
#include <tchar.h>
|
|
#include <iostream>
|
|
|
|
|
|
WCHAR *qStringToWideChar(const QString &str)
|
|
{
|
|
if (str.isNull())
|
|
return 0;
|
|
WCHAR *result = new WCHAR[str.length() + 1];
|
|
for (int i = 0; i < str.length(); ++i)
|
|
result[i] = str[i].unicode();
|
|
result[str.length()] = 0;
|
|
return result;
|
|
}
|
|
|
|
void startProcess(QString argv)
|
|
{
|
|
WCHAR* exe = qStringToWideChar(argv);
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory( &si, sizeof(si) );
|
|
si.cb = sizeof(si);
|
|
ZeroMemory( &pi, sizeof(pi) );
|
|
|
|
if( !CreateProcessW( NULL,
|
|
exe,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_NO_WINDOW,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi )
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
WaitForSingleObject( pi.hProcess, INFINITE );
|
|
|
|
CloseHandle( pi.hProcess );
|
|
CloseHandle( pi.hThread );
|
|
}
|
|
|
|
CompressionThread::CompressionThread(QStringList list, QString orig_dir, QString dir, QString format, QString suffix, QStringList quality, bool checked, QList<int> w, QList<int> h, bool fixed, bool keepARatio, bool notEnlarge, bool resize, bool structure,
|
|
QObject *parent)
|
|
: QThread(parent)
|
|
{
|
|
t_list = list;
|
|
t_dir = dir;
|
|
t_format = format;
|
|
t_suffix = suffix;
|
|
t_quality = quality;
|
|
t_checked = checked;
|
|
t_w = w;
|
|
t_h = h;
|
|
t_fixed = fixed;
|
|
t_keepARatio = keepARatio;
|
|
t_notEnlarge = notEnlarge;
|
|
t_resize = resize;
|
|
t_structure = structure;
|
|
t_orig_dir = orig_dir;
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
settings.setIniCodec("UTF-8");
|
|
#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
}
|
|
|
|
QString t_getRatio(int origSize, int newSize)
|
|
{
|
|
int ratio = newSize * 100 / origSize;
|
|
if (ratio <= 100)
|
|
{
|
|
return QString::number(ratio - 100) + " %";
|
|
}
|
|
else
|
|
{
|
|
return "+" + QString::number(ratio - 100) + " %";
|
|
}
|
|
}
|
|
|
|
void CompressionThread::run()
|
|
{
|
|
bool sameFormat = false;
|
|
QString t_dir_original = t_dir;
|
|
if (t_format == "null")
|
|
{
|
|
sameFormat = true;
|
|
}
|
|
bool no_enlarge = settings.value("Preferences/noenlarge").value<bool>();
|
|
if (no_enlarge)
|
|
{
|
|
CompressionThread::noEnlarge();
|
|
return;
|
|
}
|
|
ImageResize imgResize;
|
|
for (int i = 0; i < t_list.count(); i++)
|
|
{
|
|
QString right_dir = "";
|
|
QString originalQuality = t_quality.at(i);
|
|
QFileInfo info(t_list.at(i));
|
|
if (info.size() == 0)
|
|
{
|
|
emit updateUI(i + 1, 0, "0%");
|
|
continue;
|
|
}
|
|
if (QFile::exists(t_list.at(i)))
|
|
{
|
|
if (sameFormat)
|
|
{
|
|
t_format = info.suffix();
|
|
if (t_format.toLower() != "jpg")
|
|
{
|
|
t_quality.replace(i, "1");
|
|
}
|
|
else
|
|
{
|
|
t_quality.replace(i, originalQuality);
|
|
}
|
|
}
|
|
int old_size = info.size();
|
|
emit processingIcon(i, info.fileName());
|
|
QImage image(t_list.at(i));
|
|
if (t_resize && t_fixed)
|
|
{
|
|
image = imgResize.fixedResize(image, t_w.at(i), t_h.at(i), t_keepARatio, t_notEnlarge);
|
|
}
|
|
else if (t_resize && t_fixed == false)
|
|
{
|
|
if (t_w.at(i) == -1 && t_h.at(i) == -1)
|
|
{
|
|
t_w.replace(i, image.width());
|
|
t_h.replace(i, image.height());
|
|
}
|
|
image = imgResize.pergentageResize(image, t_w.at(i), t_h.at(i));
|
|
}
|
|
if (t_checked)
|
|
{
|
|
t_dir = info.path();
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix, t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
else if (t_structure)
|
|
{
|
|
right_dir = info.path().remove(t_orig_dir.replace('\\', '/'), Qt::CaseSensitive);
|
|
right_dir = t_dir_original + right_dir;
|
|
right_dir.replace('\\', '/');
|
|
t_dir = right_dir;
|
|
if (!QDir(t_dir).exists())
|
|
{
|
|
if (!QDir().mkpath(t_dir))
|
|
{
|
|
emit errorMessageBox();
|
|
return;
|
|
}
|
|
}
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix, t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
else
|
|
{
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix, t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
|
|
|
|
if (settings.value("Preferences/exif").value<bool>() && t_format.toLower() == "jpg")
|
|
{
|
|
QString exec = "tools\\exif_copy.exe \"" + t_list.at(i) + "\" \"" + t_dir + "\\" + info.completeBaseName() + t_suffix +"\"";
|
|
startProcess(exec);
|
|
}
|
|
QFile newImage(t_dir + "/" + info.completeBaseName() + t_suffix);
|
|
QFileInfo newInfo;
|
|
if (QFile::exists(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format))
|
|
{
|
|
QFile::remove(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
}
|
|
newImage.rename(t_dir + "/" + info.completeBaseName() + t_suffix, t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
newInfo.setFile(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
int size = newInfo.size();
|
|
QString ratio = t_getRatio(old_size, newInfo.size());
|
|
if(settings.value("Preferences/keepdate").value<bool>())
|
|
{
|
|
CompressionThread::keepDate(t_list.at(i), newInfo.filePath());
|
|
}
|
|
|
|
emit updateUI(i + 1, size, ratio);
|
|
}
|
|
else
|
|
{
|
|
emit updateUI(i + 1, -1, "0%");
|
|
}
|
|
}
|
|
exit();
|
|
}
|
|
|
|
void CompressionThread::noEnlarge()
|
|
{
|
|
ImageResize imgResize;
|
|
QString t_dir_original = t_dir;
|
|
bool sameFormat = false;
|
|
if (t_format == "null")
|
|
{
|
|
sameFormat = true;
|
|
}
|
|
for (int i = 0; i < t_list.count(); i++)
|
|
{
|
|
QString originalQuality = t_quality.at(i);
|
|
QString right_dir = "";
|
|
QFileInfo info(t_list.at(i));
|
|
if (info.size() == 0)
|
|
{
|
|
emit updateUI(i + 1, 0, "0%");
|
|
continue;
|
|
}
|
|
if (QFile::exists(t_list.at(i)))
|
|
{
|
|
if (sameFormat)
|
|
{
|
|
t_format = info.suffix();
|
|
if (t_format.toLower() != "jpg")
|
|
{
|
|
t_quality.replace(i, "1");
|
|
}
|
|
else
|
|
{
|
|
t_quality.replace(i, originalQuality);
|
|
}
|
|
}
|
|
int old_size = info.size();
|
|
emit processingIcon(i, info.fileName());
|
|
QImage image(t_list.at(i));
|
|
if (t_resize && t_fixed)
|
|
{
|
|
image = imgResize.fixedResize(image, t_w.at(i), t_h.at(i), t_keepARatio, t_notEnlarge);
|
|
}
|
|
else if (t_resize && t_fixed == false)
|
|
{
|
|
image = imgResize.pergentageResize(image, t_w.at(i), t_h.at(i));
|
|
}
|
|
if (t_checked)
|
|
{
|
|
t_dir = info.path();
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format + ".ckd", t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
else if (t_structure)
|
|
{
|
|
right_dir = info.path().remove(t_orig_dir.replace('\\', '/'), Qt::CaseSensitive);
|
|
right_dir = t_dir_original + right_dir;
|
|
right_dir.replace('\\', '/');
|
|
t_dir = right_dir;
|
|
if (!QDir(t_dir).exists())
|
|
{
|
|
if (!QDir().mkdir(t_dir))
|
|
{
|
|
emit errorMessageBox();
|
|
return;
|
|
}
|
|
}
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix, t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
else
|
|
{
|
|
image.save(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format + ".ckd", t_format.toLatin1(), t_quality.at(i).toInt());
|
|
/*if (t_format.toLatin1().toLower() == "png" && settings.value("Preferences/pngcompression").value<bool>())
|
|
{
|
|
CompressionThread::optimizePNG(t_dir + "/" + info.completeBaseName() + t_suffix, settings.value("Preferences/pnglevel").value<int>());
|
|
}*/
|
|
}
|
|
|
|
if (settings.value("Preferences/exif").value<bool>() && t_format.toLower() == "jpg")
|
|
{
|
|
QString exec = "tools\\exif_copy.exe \"" + t_list.at(i) + "\" \"" + t_dir + "\\" + info.completeBaseName() + t_suffix + "." + t_format + "\"";
|
|
startProcess(exec);
|
|
}
|
|
|
|
QFileInfo newInfo(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format + ".ckd");
|
|
int size = newInfo.size();
|
|
QString ratio = t_getRatio(old_size, newInfo.size());
|
|
|
|
if (newInfo.size() > info.size())
|
|
{
|
|
size *= -1;
|
|
QFile::remove(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format + ".ckd");
|
|
}
|
|
else
|
|
{
|
|
QFile::remove(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
QFile::rename(t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format + ".ckd", t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
}
|
|
|
|
if(settings.value("Preferences/keepdate").value<bool>())
|
|
{
|
|
CompressionThread::keepDate(t_list.at(i), t_dir + "/" + info.completeBaseName() + t_suffix + "." + t_format);
|
|
}
|
|
|
|
emit updateUI(i + 1, size, ratio);
|
|
}
|
|
else if (info.size() == 0)
|
|
{
|
|
emit updateUI(i + 1, 0, "0%");
|
|
}
|
|
else
|
|
{
|
|
emit updateUI(i + 1, -1, "0%");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CompressionThread::keepDate(QString orig, QString dest)
|
|
{
|
|
HANDLE hFile, hFile2;
|
|
|
|
FILETIME ftCreate, ftAccess, ftWrite;
|
|
hFile = CreateFile(qStringToWideChar(orig), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite);
|
|
|
|
hFile2 = CreateFile(qStringToWideChar(dest), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
SetFileTime(hFile2, &ftCreate, &ftAccess, &ftWrite);
|
|
|
|
CloseHandle(hFile);
|
|
CloseHandle(hFile2);
|
|
}
|
|
|
|
void CompressionThread::optimizePNG(QString file, int level)
|
|
{
|
|
QString exec = "tools\\optipng.exe -o" + QString::number(level) + " \"" + file + "\"";
|
|
startProcess(exec);
|
|
}
|