diff --git a/.gitmodules b/.gitmodules
index e4f2111d..dc76d6fb 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "easyexif/easyexif"]
path = easyexif/easyexif
url = https://github.com/mayanklahiri/easyexif
+[submodule "zimg/zimg"]
+ path = zimg/zimg
+ url = https://github.com/sekrit-twc/zimg
diff --git a/QVproject.pro b/QVproject.pro
index c44d27bc..94c1cb1f 100644
--- a/QVproject.pro
+++ b/QVproject.pro
@@ -5,11 +5,12 @@ SUBDIRS = \
easyexif \
unrar \
fileloader \
+ zimg \
QuickViewer \
# QuickCatalog
fileloader.depends = Qt7z/Qt7z/qt7z.pro unrar
-QuickViewer.depends = ResizeHalf/resizehalf.pro easyexif fileloader
+QuickViewer.depends = ResizeHalf/resizehalf.pro easyexif fileloader zimg
diff --git a/QuickViewer/QuickViewer.pro b/QuickViewer/QuickViewer.pro
index cf32ee9e..c870fc07 100644
--- a/QuickViewer/QuickViewer.pro
+++ b/QuickViewer/QuickViewer.pro
@@ -8,7 +8,7 @@ QT += core gui opengl concurrent opengl-private sql
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-VERSION = 0.6.6
+VERSION = 0.7.0
TARGET = QuickViewer
TEMPLATE = app
@@ -16,7 +16,7 @@ CONFIG += plugin
QMAKE_TARGET_COMPANY = KATO Kanryu(k.kanryu@gmail.com)
QMAKE_TARGET_PRODUCT = QuickViewer
-QMAKE_TARGET_DESCRIPTION = A image viewer for folders/archives, it can show images very fast
+QMAKE_TARGET_DESCRIPTION = QuickViewer for folders/archives
QMAKE_TARGET_COPYRIGHT = (C) 2017 KATO Kanryu
DEFINES += \
@@ -72,9 +72,10 @@ win32 { !CONFIG(debug, debug|release) {
INCLUDEPATH += ../ResizeHalf/ResizeHalf
INCLUDEPATH += ../easyexif/easyexif
INCLUDEPATH += ../fileloader
+INCLUDEPATH += ../zimg
INCLUDEPATH += ./src ./src/catalog ./src/widgets ./src/models ./src/folderview
-LIBS += -L../lib -leasyexif -lresizehalf -lfileloader -lQt7z -lunrar
+LIBS += -L../lib -leasyexif -lresizehalf -lfileloader -lQt7z -lunrar -lzimg
win32 {
QMAKE_CXXFLAGS += /wd4819
@@ -106,7 +107,8 @@ SOURCES += \
src/widgets/pageslider.cpp \
src/widgets/shortcutbutton.cpp \
src/folderview/folderitemmodel.cpp \
- src/folderview/folderwindow.cpp
+ src/folderview/folderwindow.cpp \
+ src/models/pagecontent.cpp
HEADERS += \
src/qv_init.h \
@@ -130,7 +132,8 @@ HEADERS += \
src/widgets/pageslider.h \
src/widgets/shortcutbutton.h \
src/folderview/folderitemmodel.h \
- src/folderview/folderwindow.h
+ src/folderview/folderwindow.h \
+ src/models/pagecontent.h
win32 {
SOURCES += src/mainwindowforwindows.cpp
diff --git a/QuickViewer/src/folderview/folderitemmodel.cpp b/QuickViewer/src/folderview/folderitemmodel.cpp
index ee38c29c..e1cee0bc 100644
--- a/QuickViewer/src/folderview/folderitemmodel.cpp
+++ b/QuickViewer/src/folderview/folderitemmodel.cpp
@@ -9,7 +9,7 @@ FolderItemModel::FolderItemModel(QObject *parent)
}
-QVariant FolderItemModel::headerData(int section, Qt::Orientation orientation, int role) const
+QVariant FolderItemModel::headerData(int section, Qt::Orientation , int role) const
{
switch(role) {
case Qt::DisplayRole:
@@ -71,7 +71,7 @@ int FolderItemModel::columnCount(const QModelIndex &) const
return m_columns;
}
-QModelIndex FolderItemModel::index(int row, int column, const QModelIndex &parent) const
+QModelIndex FolderItemModel::index(int row, int column, const QModelIndex &) const
{
// if(column > 1 || !m_searchedVolumes)
// return QModelIndex();
diff --git a/QuickViewer/src/folderview/folderwindow.cpp b/QuickViewer/src/folderview/folderwindow.cpp
index 52ac30c7..ded54547 100644
--- a/QuickViewer/src/folderview/folderwindow.cpp
+++ b/QuickViewer/src/folderview/folderwindow.cpp
@@ -7,7 +7,7 @@
#include "models/filevolume.h"
#include "models/qvapplication.h"
-FolderWindow::FolderWindow(QWidget *parent, Ui::MainWindow *uiMain)
+FolderWindow::FolderWindow(QWidget *parent, Ui::MainWindow *)
: QWidget(parent)
, ui(new Ui::FolderWindow)
, m_itemModel(this)
@@ -19,8 +19,6 @@ FolderWindow::FolderWindow(QWidget *parent, Ui::MainWindow *uiMain)
ui->folderView->installEventFilter(this);
// folderView
-// m_itemModel.setHeaderData(0, Qt::Horizontal, tr("Name"));
-// m_itemModel.setHeaderData(1, Qt::Horizontal, tr("ModifiedTime"));
ui->folderView->setModel(&m_itemModel);
resetSortMode();
@@ -62,8 +60,8 @@ static QModelIndex selectedIdx;
bool FolderWindow::eventFilter(QObject *obj, QEvent *event)
{
- qDebug() << obj << event << event->type();
- QMouseEvent *mouseEvent = NULL;
+// qDebug() << obj << event << event->type();
+// QMouseEvent *mouseEvent = NULL;
QContextMenuEvent *contextEvent = nullptr;
switch (event->type()) {
case QEvent::ContextMenu:
@@ -114,9 +112,8 @@ void FolderWindow::dropEvent(QDropEvent *e)
void FolderWindow::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
- QFontMetrics fontMetrics(ui->pathLabel->font());
- QString pathLabelTxt = fontMetrics.elidedText(m_currentPath, Qt::ElideMiddle, event->size().width()-10);
- ui->pathLabel->setText(pathLabelTxt);
+ resetPathLabel(event->size().width());
+
}
static bool filenameLessThan(const FolderItem& lhs, const FolderItem& rhs)
@@ -137,6 +134,8 @@ static bool updatedAtLessThan(const FolderItem& lhs, const FolderItem& rhs)
void FolderWindow::setFolderPath(QString path, bool showParent)
{
+ if(path.isEmpty())
+ path = qApp->HomeFolderPath();
QFileInfo fileinfo(path);
if(!fileinfo.exists())
return;
@@ -148,13 +147,8 @@ void FolderWindow::setFolderPath(QString path, bool showParent)
dir.setPath(QDir::toNativeSeparators(fileinfo.dir().path()));
}
-// m_currentPath = fileinfo.isDir() ? path : fileinfo.canonicalPath();
m_currentPath = dir.path();
-
- // Elide text(Otherwise the width of the main window will be forcibly changed)
- QFontMetrics fontMetrics(ui->pathLabel->font());
- QString pathLabelTxt = fontMetrics.elidedText(m_currentPath, Qt::ElideMiddle, width()-10);
- ui->pathLabel->setText(pathLabelTxt);
+ resetPathLabel(width());
m_volumes.clear();
{
@@ -202,12 +196,22 @@ void FolderWindow::resetSortMode()
: ui->actionOrderByUpdatedAt->text());
}
+void FolderWindow::resetPathLabel(int maxWidth)
+{
+ QFontMetrics fontMetrics(ui->pathLabel->font());
+ QString pathLabelTxt = fontMetrics.elidedText(
+ QDir::toNativeSeparators(m_currentPath), Qt::ElideMiddle, maxWidth-10);
+ ui->pathLabel->setText(pathLabelTxt);
+}
+
+
void FolderWindow::on_home_triggered()
{
- if(m_historyNext.contains(m_currentPath))
- m_historyNext.removeOne(m_currentPath);
- m_historyNext << m_currentPath;
- setFolderPath(qApp->HomeFolderPath(), false);
+ if(m_historyPrev.contains(m_currentPath))
+ m_historyPrev.removeOne(m_currentPath);
+ m_historyPrev << m_currentPath;
+ setFolderPath(qApp->HomeFolderPath());
+ emit openVolume(qApp->HomeFolderPath());
}
void FolderWindow::on_prev_triggered()
@@ -217,7 +221,10 @@ void FolderWindow::on_prev_triggered()
if(m_historyNext.contains(m_currentPath))
m_historyNext.removeOne(m_currentPath);
m_historyNext << m_currentPath;
- setFolderPath(m_historyPrev.takeLast(), false);
+ QString path = m_historyPrev.takeLast();
+
+ setFolderPath(path, false);
+ emit openVolume(path);
}
void FolderWindow::on_next_triggered()
@@ -227,7 +234,9 @@ void FolderWindow::on_next_triggered()
if(m_historyPrev.contains(m_currentPath))
m_historyPrev.removeOne(m_currentPath);
m_historyPrev << m_currentPath;
- setFolderPath(m_historyNext.takeLast(), false);
+ QString path = m_historyNext.takeLast();
+ setFolderPath(path, false);
+ emit openVolume(path);
}
void FolderWindow::on_parent_triggered()
@@ -236,6 +245,7 @@ void FolderWindow::on_parent_triggered()
return;
QFileInfo info(m_currentPath);
setFolderPath(info.canonicalPath(), false);
+ emit openVolume(info.canonicalPath());
}
void FolderWindow::on_reload_triggered()
@@ -287,6 +297,10 @@ void FolderWindow::on_itemDoubleClicked(const QModelIndex &index)
QDir dir(m_currentPath);
QString subpath = dir.absoluteFilePath(item.name);
emit openVolume(subpath);
+
+ if(m_historyPrev.contains(m_currentPath))
+ m_historyPrev.removeOne(m_currentPath);
+ m_historyPrev << m_currentPath;
setFolderPath(subpath, false);
}
diff --git a/QuickViewer/src/folderview/folderwindow.h b/QuickViewer/src/folderview/folderwindow.h
index d988ebcd..93003340 100644
--- a/QuickViewer/src/folderview/folderwindow.h
+++ b/QuickViewer/src/folderview/folderwindow.h
@@ -26,6 +26,8 @@ class FolderWindow : public QWidget
void setFolderPath(QString path, bool showParent=true);
void reset();
void resetSortMode();
+ void resetPathLabel(int maxWidth);
+ QString currentPath() { return m_currentPath; }
public slots:
void on_home_triggered();
diff --git a/QuickViewer/src/folderview/folderwindow.ui b/QuickViewer/src/folderview/folderwindow.ui
index e3951ef2..4f4c8b9d 100644
--- a/QuickViewer/src/folderview/folderwindow.ui
+++ b/QuickViewer/src/folderview/folderwindow.ui
@@ -55,14 +55,14 @@
@@ -1930,6 +1940,22 @@
+
+ actionShaderBilinearBeforeCpuBicubic
+ triggered()
+ MainWindow
+ on_shaderBilinearBeforeCpuBicubic_triggered()
+
+
+ -1
+ -1
+
+
+ 350
+ 294
+
+
+
on_file_changed(QString)
@@ -1981,5 +2007,6 @@
on_catalogIconLongText_triggered(bool)
on_folderWindow_triggered()
on_folderWindowClosed_triggered()
+ on_shaderBilinearBeforeCpuBicubic_triggered()
diff --git a/QuickViewer/src/models/filevolume.cpp b/QuickViewer/src/models/filevolume.cpp
index d65d724b..c2d6160d 100644
--- a/QuickViewer/src/models/filevolume.cpp
+++ b/QuickViewer/src/models/filevolume.cpp
@@ -7,6 +7,7 @@
#include "fileloaderrararchive.h"
#include "ResizeHalf.h"
#include "qvapplication.h"
+#include "qzimg.h"
IFileVolume::IFileVolume(QObject *parent, IFileLoader* loader)
: QObject(parent)
@@ -204,7 +205,14 @@ ImageContent IFileVolume::futureLoadImageFromFileVolume(IFileVolume* volume, QSt
loadingSize = QSize((loadingSize.width()+1) >> 1,(loadingSize.height()+1) >> 1);
reader.setScaledSize(loadingSize);
}
- QImage src = reader.read();
+ QImage src;
+ if(reader.imageFormat() != QImage::Format_Indexed8) {
+ src = QZimg::createPackedImage(loadingSize, reader.imageFormat());
+ reader.read(&src);
+ } else {
+ QImage tmp = reader.read();
+ src = QZimg::toPackedImage(tmp);
+ }
// parsing JPEG EXIF
easyexif::EXIFInfo info;
diff --git a/QuickViewer/src/models/pagecontent.cpp b/QuickViewer/src/models/pagecontent.cpp
new file mode 100644
index 00000000..c38b45b0
--- /dev/null
+++ b/QuickViewer/src/models/pagecontent.cpp
@@ -0,0 +1,155 @@
+#include
+
+#include "pagecontent.h"
+#include "qvapplication.h"
+#include "qzimg.h"
+
+PageContent::PageContent(QObject* parent)
+ : QObject(parent)
+ , Ic()
+ , GrItem(nullptr)
+ , Rotate(0)
+ , m_resizeGeneratingState(0)
+{
+
+}
+
+PageContent::PageContent(QObject* parent, QGraphicsScene *s, ImageContent ic)
+ : QObject(parent)
+ , Scene(s)
+ , Ic(ic)
+ , GrItem(nullptr)
+ , Rotate(0)
+ , m_resizeGeneratingState(0)
+{
+ if(ic.Info.ImageWidth > 0 && ic.Info.Orientation != 1) {
+ switch(ic.Info.Orientation) {
+ case 6: // left 90 digree turned
+ Rotate = 90;
+ break;
+ case 8: // right 90 digree turned
+ Rotate = 270;
+ break;
+ }
+ }
+ initializePage();
+}
+
+PageContent::PageContent(const PageContent &rhs)
+ : QObject(rhs.parent())
+ , Scene(rhs.Scene)
+ , Ic(rhs.Ic)
+ , ResizedPage(rhs.ResizedPage)
+ , GrItem(rhs.GrItem)
+ , Rotate(rhs.Rotate)
+ , m_resizeGeneratingState(0)
+{
+
+}
+
+PageContent &PageContent::operator=(const PageContent &rhs) {
+ Scene = rhs.Scene;
+ Ic = rhs.Ic;
+ ResizedPage = rhs.ResizedPage;
+ GrItem = rhs.GrItem;
+ Rotate = rhs.Rotate;
+ m_resizeGeneratingState = 0;
+ return *this;
+}
+
+QPoint PageContent::Offset(int rotateOffset) {
+ int rot = (Rotate+rotateOffset) % 360;
+ switch(rot) {
+ case 90: return QPoint(Ic.Image.height(), 0);
+ case 180: return QPoint(Ic.Image.width(), Ic.Image.height());
+ case 270: return QPoint(0, Ic.Image.width());
+ default: return QPoint();
+ }
+}
+
+QSize PageContent::CurrentSize(int rotateOffset) {
+ int rot = (Rotate+rotateOffset) % 360;
+ return rot==90 || rot==270 ? QSize(Ic.Image.height(), Ic.Image.width()) : Ic.Image.size();
+}
+
+QRect PageContent::setPageLayoutFitting(QRect viewport, PageContent::Fitting fitting, int rotateOffset) {
+ QSize currentSize = CurrentSize(rotateOffset);
+ QSize newsize = currentSize.scaled(viewport.size(), Qt::KeepAspectRatio);
+ qreal scale = 1.0*newsize.width()/currentSize.width();
+
+ QPoint of = Offset(rotateOffset);
+ of *= scale;
+
+ QRect drawRect;
+ if(newsize.height() == viewport.height()) { // fitting on upper and bottom
+ int ofsinviewport = fitting==FitLeft ? 0 : fitting==FitCenter ? (viewport.width()-newsize.width())/2 : viewport.width()-newsize.width();
+ drawRect = QRect(QPoint(of.x() + viewport.x() + ofsinviewport, of.y()), newsize);
+ } else { // fitting on left and right
+ drawRect = QRect(QPoint(of.x() + viewport.x(), of.y() + (viewport.height()-newsize.height())/2), newsize);
+ }
+// GrItem->setScale(scale);
+// GrItem->setRotation(Rotate+rotateOffset);
+// GrItem->setPos(drawRect.topLeft());
+ applyResize(scale, rotateOffset, drawRect.topLeft(), newsize);
+ return drawRect;
+}
+
+QRect PageContent::setPageLayoutManual(QRect viewport, PageContent::Fitting fitting, qreal scale, int rotateOffset) {
+ QSize currentSize = CurrentSize(rotateOffset);
+ QSize newsize = currentSize * scale;
+
+ QPoint of = Offset(rotateOffset);
+ of *= scale;
+
+ int ofsinviewport = fitting==FitLeft ? 0 : fitting==FitCenter ? (viewport.width()-newsize.width())/2 : viewport.width()-newsize.width();
+ QRect drawRect(QPoint(of.x() + viewport.x() + ofsinviewport, of.y()), newsize);
+
+ applyResize(scale, rotateOffset, drawRect.topLeft(), newsize);
+ return drawRect;
+}
+
+void PageContent::applyResize(qreal scale, int rotateOffset, QPoint pos, QSize newsize)
+{
+ // need CPU resizing
+ if(qApp->Effect() > qvEnums::UsingCpuResizer && qApp->Effect() < qvEnums::UsingSomeShader) {
+ if(!ResizedPage.isNull() && ResizedPage.size() != newsize) {
+ initializePage();
+ }
+ if(ResizedPage.isNull() && m_resizeGeneratingState==0) {
+ m_resizeGeneratingState = 1;
+ QFuture future = QtConcurrent::run(QZimg::scaled, Ic.Image.toImage(), newsize, Qt::IgnoreAspectRatio, QZimg::ResizeBicubic);
+ connect(&generateWatcher, SIGNAL(finished()), this, SLOT(on_resizeFinished_trigger()));
+ generateWatcher.setFuture(future);
+ }
+ if(!ResizedPage.isNull() && m_resizeGeneratingState==2) {
+ Scene->removeItem(GrItem);
+ delete GrItem;
+ GrItem = Scene->addPixmap(ResizedPage);
+ GrItem->setRotation(Rotate);
+ }
+ }
+ GrItem->setScale(ResizedPage.isNull() ? scale : 1.0);
+ GrItem->setRotation(Rotate+rotateOffset);
+ GrItem->setPos(pos);
+}
+
+void PageContent::initializePage()
+{
+ if(GrItem) {
+ Scene->removeItem(GrItem);
+ delete GrItem;
+ }
+ GrItem = Scene->addPixmap(Ic.Image);
+ GrItem->setRotation(Rotate);
+ ResizedPage = QPixmap();
+ m_resizeGeneratingState = 0;
+}
+
+void PageContent::on_resizeFinished_trigger()
+{
+ ResizedPage = QPixmap::fromImage(generateWatcher.result());
+
+ m_resizeGeneratingState = 2;
+ disconnect(&generateWatcher, SIGNAL(finished()), this, SLOT(on_resizeFinished_trigger()));
+ emit resizeFinished();
+}
diff --git a/QuickViewer/src/models/pagecontent.h b/QuickViewer/src/models/pagecontent.h
new file mode 100644
index 00000000..d4434ce5
--- /dev/null
+++ b/QuickViewer/src/models/pagecontent.h
@@ -0,0 +1,65 @@
+#ifndef PAGECONTENT_H
+#define PAGECONTENT_H
+
+#include
+#include
+
+#include "filevolume.h"
+
+/**
+ * @brief PageContent
+ * contains the informations of a Page
+ */
+class PageContent : public QObject
+{
+ Q_OBJECT
+public:
+ QGraphicsScene *Scene;
+ ImageContent Ic;
+ /**
+ * @brief GrItem
+ * Page image is used as a QGraphicsItem. it will be registed to the scene
+ */
+ QGraphicsItem* GrItem;
+ /**
+ * @brief Resized
+ * Store the image changed to the specified size (newsize)
+ */
+ QPixmap ResizedPage;
+ QFutureWatcher generateWatcher;
+ /**
+ * @brief Rotate: rotation as digrees
+ */
+ int Rotate;
+ enum Fitting {
+ FitCenter,
+ FitLeft,
+ FitRight
+ };
+ PageContent(QObject* parent=nullptr);
+ PageContent(QObject* parent, QGraphicsScene *s, ImageContent ic);
+ PageContent(const PageContent& rhs);
+ PageContent& operator=(const PageContent& rhs);
+
+ QPoint Offset(int rotateOffset=0);
+ QSize CurrentSize(int rotateOffset=0);
+
+ /**
+ * @brief setPageLayout set each image on the page
+ * @param viewport: the image must be inscribed in the viewport area
+ */
+ QRect setPageLayoutFitting(QRect viewport, Fitting fitting, int rotateOffset=0);
+ QRect setPageLayoutManual(QRect viewport, Fitting fitting, qreal scale, int rotateOffset=0);
+
+ void applyResize(qreal scale, int rotateOffset, QPoint pos, QSize newsize);
+ void initializePage();
+signals:
+ void resizeFinished();
+public slots:
+ void on_resizeFinished_trigger();
+
+private:
+ int m_resizeGeneratingState;
+};
+
+#endif // PAGECONTENT_H
diff --git a/QuickViewer/src/models/qvapplication.cpp b/QuickViewer/src/models/qvapplication.cpp
index 61259301..b4922892 100644
--- a/QuickViewer/src/models/qvapplication.cpp
+++ b/QuickViewer/src/models/qvapplication.cpp
@@ -47,6 +47,7 @@ void QVApplication::registDefaultKeyMap()
m_keyConfigDefauls["actionZoomIn"] = QKeySequence("K, Num++");
m_keyConfigDefauls["actionZoomOut"] = QKeySequence("J, Num+-");
+ m_keyConfigDefauls["actionShowFolder"] = QKeySequence("F4");
m_keyConfigDefauls["actionShowCatalog"] = QKeySequence("Ctrl+/, F6");
m_keyConfigDefauls["actionSlideShow"] = QKeySequence("F7");
m_keyConfigDefauls["actionStayOnTop"] = QKeySequence("F8");
@@ -96,6 +97,9 @@ void QVApplication::registActions(Ui::MainWindow *ui)
registAction("actionPrevOnePage", ui->actionPrevOnePage);
registAction("actionSlideShow", ui->actionSlideShow);
+ // Folder
+ registAction("actionShowFolder", ui->actionShowFolder);
+
// Catalog
registAction("actionShowCatalog", ui->actionShowCatalog);
registAction("actionSearchTitleWithOptions", ui->actionSearchTitleWithOptions);
@@ -139,6 +143,7 @@ void QVApplication::registActions(Ui::MainWindow *ui)
registAction("actionShaderBilinear", ui->actionShaderBilinear);
registAction("actionShaderBicubic", ui->actionShaderBicubic);
registAction("actionShaderLanczos", ui->actionShaderLanczos);
+ registAction("actionShaderBilinearBeforeCpuBicubic", ui->actionShaderBilinearBeforeCpuBicubic);
// Help
registAction("actionOpenKeyConfig", ui->actionOpenKeyConfig);
@@ -279,7 +284,7 @@ void QVApplication::loadSettings()
m_settings.endGroup();
m_settings.beginGroup("Shader");
- QString effectstring = m_settings.value("Effect", "Bilinear").toString();
+ QString effectstring = m_settings.value("Effect", "BilinearAndCpuBicubic").toString();
m_effect = ShaderManager::stringToShaderEffect(effectstring);
m_bicubicShaderPath = m_settings.value("BicubicShaderPath", "shaders/bicubic.frag").toString();
m_lanczosShaderPath = m_settings.value("LanczosShaderPath", "shaders/lanczos.frag").toString();
diff --git a/QuickViewer/src/qv_init.h b/QuickViewer/src/qv_init.h
index de927d18..48109089 100644
--- a/QuickViewer/src/qv_init.h
+++ b/QuickViewer/src/qv_init.h
@@ -18,6 +18,13 @@ class qvEnums : public QObject
UnPrepared,
NearestNeighbor,
Bilinear,
+
+ UsingCpuResizer,
+ BilinearAndCpuBicubic,
+ BilinearAndCpuSpline16,
+ BilinearAndCpuSpline36,
+ BilinearAndCpuLanczos,
+
UsingSomeShader,
Bicubic,
Lanczos
diff --git a/QuickViewer/translations/quickviewer_ja.qm b/QuickViewer/translations/quickviewer_ja.qm
index 55fda718..76c420cb 100644
Binary files a/QuickViewer/translations/quickviewer_ja.qm and b/QuickViewer/translations/quickviewer_ja.qm differ
diff --git a/QuickViewer/translations/quickviewer_ja.ts b/QuickViewer/translations/quickviewer_ja.ts
index 17a8462e..bdd477aa 100644
--- a/QuickViewer/translations/quickviewer_ja.ts
+++ b/QuickViewer/translations/quickviewer_ja.ts
@@ -310,11 +310,93 @@
時計回りに270°回転
+
+ FolderItemModel
+
+ Name
+ 名前
+
+
+ ModifiedTime
+ 更新日時
+
+
+
+ FolderWindow
+
+ FolderWindow
+ フォルダ一覧
+
+
+ &Sort
+ 並べ替え(&S)
+
+
+ Current Folder
+ 現在のフォルダ
+
+
+ My Pictures
+ マイピクチャ
+
+
+ Move to Home
+ ホームフォルダに移動
+
+
+ Prev
+ 前へ
+
+
+ Next
+ 次へ
+
+
+ To parent folder
+ 上のフォルダ
+
+
+ Reload
+ 更新
+
+
+ Name
+ 名前順
+
+
+ Home
+ ホームフォルダ
+
+
+ ToParent
+ 上のフォルダ
+
+
+ Others
+ その他
+
+
+ ModifiedTime
+ 更新日時順
+
+
+ set the folder as Home
+ このフォルダをホームフォルダにする
+
+
+ No folders or archives
+ フォルダやアーカイブが見つかりません
+
+
+ ChangeSorting
+ 並べ替える方法を変更します
+
+
ImageView
NOT IMAGE
- 画像以外のファイルです
+ 画像以外のファイルです
Launching Windows Explorer failed
@@ -596,7 +678,7 @@
open error
- 開くときに問題がありました
+ 開くときに問題がありました
Can't be opened. Is there no images?
@@ -832,7 +914,7 @@
&Bilinear interpolation (standard)
- バイリニア補間(&B 標準)
+ バイリニア補間(&B 標準)
Bi&cubic interpolation (slow)
@@ -928,7 +1010,19 @@
Show large &grid for long titles
- 長いタイトルを表示するために枠を大きめにする
+ 長いタイトルを表示するために枠を大きめにする(&G)
+
+
+ &Bilinear interpolation (fast)
+ バイリニア補間(&B 高速)
+
+
+ Show&Folder
+ フォルダを表示(&F)
+
+
+ CPU Bicubic after GPU Bilinear(standard)
+ GPUによるバイキュービックの後、CPUによるバイキュービック(標準)
diff --git a/zimg/qzimg.cpp b/zimg/qzimg.cpp
new file mode 100644
index 00000000..eea753b7
--- /dev/null
+++ b/zimg/qzimg.cpp
@@ -0,0 +1,304 @@
+#include
+#include
+
+#include "qzimg.h"
+#include "api/zimg++.hpp"
+#include "aligned_malloc.h"
+
+class QZimgPrivate
+{
+
+};
+struct Callback {
+ const zimgxx::zimage_buffer *buffer;
+ const QImage *img;
+};
+struct AlignedBuffer {
+ AlignedBuffer(){}
+ AlignedBuffer(size_t sz){
+ handle.reset(aligned_malloc(sz, 64), &aligned_free);
+ }
+ std::shared_ptr handle;
+};
+struct AlignedBuffer2 : public AlignedBuffer {
+ zimgxx::zimage_buffer buffer;
+ AlignedBuffer2(const zimgxx::zimage_format &format, unsigned count)
+ {
+ unsigned char *ptr;
+
+ unsigned mask = zimg_select_buffer_mask(count);
+ size_t channel_size[3] = { 0 };
+ size_t pixel_size;
+
+ count = (mask == ZIMG_BUFFER_MAX) ? format.height : mask + 1;
+
+ if (format.pixel_type == ZIMG_PIXEL_FLOAT)
+ pixel_size = sizeof(float);
+ else if (format.pixel_type == ZIMG_PIXEL_WORD || format.pixel_type == ZIMG_PIXEL_HALF)
+ pixel_size = sizeof(uint16_t);
+ else
+ pixel_size = sizeof(uint8_t);
+
+ for (unsigned p = 0; p < (format.color_family == ZIMG_COLOR_GREY ? 1U : 3U); ++p) {
+ unsigned count_plane = p ? count : count >> format.subsample_h;
+ unsigned mask_plane = (mask == ZIMG_BUFFER_MAX) ? mask : mask >> format.subsample_h;
+ size_t row_size = format.width * pixel_size;
+ ptrdiff_t stride = row_size % 64 ? row_size - row_size % 64 + 64 : row_size;
+
+ buffer.mask(p) = mask_plane;
+ buffer.stride(p) = stride;
+ channel_size[p] = static_cast(stride) * count_plane;
+ }
+
+ handle.reset(aligned_malloc(channel_size[0] + channel_size[1] + channel_size[2], 64), &aligned_free);
+ ptr = static_cast(handle.get());
+
+ for (unsigned p = 0; p < (format.color_family == ZIMG_COLOR_GREY ? 1U : 3U); ++p) {
+ buffer.data(p) = ptr;
+ ptr += channel_size[p];
+ }
+ }
+};
+
+zimgxx::zimage_buffer allocate_buffer(const zimgxx::zimage_format &format, unsigned count)
+{
+ zimgxx::zimage_buffer buffer;
+ std::shared_ptr handle;
+ unsigned char *ptr;
+
+ unsigned mask = zimg_select_buffer_mask(count);
+ size_t channel_size[3] = { 0 };
+ size_t pixel_size;
+
+ count = (mask == ZIMG_BUFFER_MAX) ? format.height : mask + 1;
+
+ if (format.pixel_type == ZIMG_PIXEL_FLOAT)
+ pixel_size = sizeof(float);
+ else if (format.pixel_type == ZIMG_PIXEL_WORD || format.pixel_type == ZIMG_PIXEL_HALF)
+ pixel_size = sizeof(uint16_t);
+ else
+ pixel_size = sizeof(uint8_t);
+
+ for (unsigned p = 0; p < (format.color_family == ZIMG_COLOR_GREY ? 1U : 3U); ++p) {
+ unsigned count_plane = p ? count : count >> format.subsample_h;
+ unsigned mask_plane = (mask == ZIMG_BUFFER_MAX) ? mask : mask >> format.subsample_h;
+ size_t row_size = format.width * pixel_size;
+ ptrdiff_t stride = row_size % 64 ? row_size - row_size % 64 + 64 : row_size;
+
+ buffer.mask(p) = mask_plane;
+ buffer.stride(p) = stride;
+ channel_size[p] = static_cast(stride) * count_plane;
+ }
+
+ handle.reset(aligned_malloc(channel_size[0] + channel_size[1] + channel_size[2], 64), &aligned_free);
+ ptr = static_cast(handle.get());
+
+ for (unsigned p = 0; p < (format.color_family == ZIMG_COLOR_GREY ? 1U : 3U); ++p) {
+ buffer.data(p) = ptr;
+ ptr += channel_size[p];
+ }
+
+ return buffer;
+}
+
+std::shared_ptr allocate_buffer(size_t size)
+{
+ return{ aligned_malloc(size, 64), &aligned_free };
+}
+
+void unpack_bgr(const void *bgr, void * const planar[3], unsigned bit_depth, unsigned left, unsigned right)
+{
+ const uint8_t *packed_bgr = static_cast(bgr);
+ uint8_t *planar_r = static_cast(planar[0]);
+ uint8_t *planar_g = static_cast(planar[1]);
+ uint8_t *planar_b = static_cast(planar[2]);
+ unsigned step = bit_depth / 8;
+ if(step == 1) {
+ ::memcpy(&planar_r[left], &packed_bgr[left], right-left);
+ return;
+ }
+
+ for (unsigned j = left; j < right; ++j) {
+ uint8_t r, g, b;
+
+ b = packed_bgr[j * step + 0];
+ g = packed_bgr[j * step + 1];
+ r = packed_bgr[j * step + 2];
+
+ planar_r[j] = r;
+ planar_g[j] = g;
+ planar_b[j] = b;
+ }
+}
+
+void pack_bgr(const void * const planar[3], void *bgr, unsigned bit_depth, unsigned left, unsigned right)
+{
+ const uint8_t *planar_r = static_cast(planar[0]);
+ const uint8_t *planar_g = static_cast(planar[1]);
+ const uint8_t *planar_b = static_cast(planar[2]);
+ uint8_t *packed_bgr = static_cast(bgr);
+ unsigned step = bit_depth / 8;
+ if(step == 1) {
+ ::memcpy(&packed_bgr[left], &planar_r[left], right-left);
+ return;
+ }
+
+ for (unsigned j = left; j < right; ++j) {
+ uint8_t r, g, b;
+
+ r = planar_r[j];
+ g = planar_g[j];
+ b = planar_b[j];
+
+ packed_bgr[j * step + 0] = b;
+ packed_bgr[j * step + 1] = g;
+ packed_bgr[j * step + 2] = r;
+ }
+}
+
+int unpack_image(void *user, unsigned i, unsigned left, unsigned right)
+{
+ const Callback *cb = static_cast(user);
+ const void *img = cb->img->bits() + i * cb->img->bytesPerLine();
+ const zimgxx::zimage_buffer &buf = *cb->buffer;
+ void *buf_data[3];
+
+ for (unsigned p = 0; p < 3; ++p) {
+ buf_data[p] = static_cast(buf.line_at(i, p));
+ }
+
+ unpack_bgr(img, buf_data, cb->img->depth(), left, right);
+ return 0;
+}
+
+int pack_image(void *user, unsigned i, unsigned left, unsigned right)
+{
+ const Callback *cb = static_cast(user);
+ void *img = const_cast(cb->img->bits()) + i * cb->img->bytesPerLine();
+ const zimgxx::zimage_buffer &buf = *cb->buffer;
+ const void *buf_data[3];
+
+ for (unsigned p = 0; p < 3; ++p) {
+ buf_data[p] = static_cast(buf.line_at(i, p));
+ }
+
+ pack_bgr(buf_data, img, cb->img->depth(), left, right);
+ return 0;
+}
+
+QZimg::QZimg(QObject *parent)
+ : QObject(parent)
+ , d(new QZimgPrivate)
+{
+
+}
+
+QZimg::~QZimg()
+{
+ delete d;
+}
+
+static void releaseBuff(void* pt)
+{
+ aligned_free(pt);
+}
+
+QImage QZimg::createPackedImage(QSize size, QImage::Format fmt, int stridePack)
+{
+ QPixelFormat pxf = QImage::toPixelFormat(fmt);
+ int bwidth = size.width();
+ if(bwidth % stridePack)
+ bwidth = (bwidth+stridePack-1)/stridePack*stridePack;
+ int bytesPerLine = bwidth*pxf.bitsPerPixel()/8;
+ uchar* buff = (uchar*)aligned_malloc(size.height()*bytesPerLine, 64);
+ return QImage(buff, size.width(), size.height(), bytesPerLine, fmt, releaseBuff, buff);
+}
+
+QImage QZimg::toPackedImage(const QImage &src, int stridePack)
+{
+ if((src.format() == QImage::Format_ARGB32 && (src.bytesPerLine() % (4*stridePack-1)) == 0)
+ || ((src.format() == QImage::Format_Grayscale8 || src.format() == QImage::Format_RGB888) && (src.bytesPerLine() % (stridePack-1)) == 0))
+ return src;
+
+ QImage img;
+ if(src.format() == QImage::Format_Indexed8) {
+ uchar* ibuff;
+ QImage tmp = src.convertToFormat(QImage::Format_Grayscale8);
+ img = createPackedImage(src.size(), QImage::Format_Grayscale8);
+ for(uint y = 0; y < tmp.height(); y++)
+ memcpy(img.bits()+y*img.bytesPerLine(), tmp.bits()+y*tmp.bytesPerLine(), tmp.bytesPerLine());
+ } else {
+ img = createPackedImage(src.size(), src.format());
+ for(uint y = 0; y < src.height(); y++)
+ memcpy(img.bits()+y*img.bytesPerLine(), src.bits()+y*src.bytesPerLine(), src.bytesPerLine());
+ }
+ return img;
+}
+
+QImage QZimg::scaled(const QImage &src, const QSize &newsize, Qt::AspectRatioMode aspectMode, QZimg::FilterMode mode)
+{
+ QImage img = toPackedImage(src);
+ zimgxx::zimage_format ifmt;
+ ifmt.width = img.width();
+ ifmt.height = img.height();
+
+ ifmt.subsample_w = 0;
+ ifmt.subsample_h = 0;
+
+ ifmt.pixel_type = ZIMG_PIXEL_BYTE;
+ ifmt.color_family = img.format() == QImage::Format_Grayscale8
+ ? ZIMG_COLOR_GREY
+ : ZIMG_COLOR_RGB;
+ ifmt.matrix_coefficients = ifmt.color_family == ZIMG_COLOR_RGB ? ZIMG_MATRIX_RGB : ZIMG_MATRIX_UNSPECIFIED;
+ ifmt.pixel_range = ZIMG_RANGE_FULL;
+
+ zimgxx::zimage_format ofmt = ifmt;
+ ofmt.height = newsize.height();
+ ofmt.width = aspectMode == Qt::IgnoreAspectRatio
+ ? newsize.width()
+ : ifmt.width*ofmt.height/ifmt.height;
+
+ zimgxx::FilterGraph graph{ zimgxx::FilterGraph::build(ifmt, ofmt) };
+
+// zimgxx::zfilter_graph_builder_params params;
+// zimgxx::FilterGraph graph{ zimgxx::FilterGraph::build(ifmt, ofmt, ¶ms) };
+
+ unsigned input_buffering = graph.get_input_buffering();
+ unsigned output_buffering = graph.get_output_buffering();
+ size_t tmp_size = graph.get_tmp_size();
+
+// qDebug() << "input buffering: " << input_buffering;
+// qDebug() << "output buffering: " << output_buffering;
+// qDebug() << "heap usage: " << tmp_size;
+// qDebug() << "img: " << img;
+ QImage oimg = createPackedImage(QSize(ofmt.width, ofmt.height), img.format());
+// qDebug() << "oimg: " << oimg;
+ uchar* obuff = oimg.bits();
+
+ AlignedBuffer2 in_buf(ifmt, input_buffering);
+ AlignedBuffer2 out_buf(ofmt, output_buffering);
+ AlignedBuffer tmp_buff(tmp_size);
+
+ Callback unpack_cb_data = { &in_buf.buffer, &img };
+ Callback pack_cb_data = { &out_buf.buffer, &oimg };
+
+// qDebug() << "resize begin: ";
+ QElapsedTimer et_qt;et_qt.start();
+ graph.process(in_buf.buffer.as_const(), out_buf.buffer, tmp_buff.handle.get(),
+ unpack_image, &unpack_cb_data, pack_image, &pack_cb_data);
+
+ qint64 t_qt = et_qt.elapsed();
+// qDebug() << "resize end. time: " << t_qt;
+
+// {
+// QImage tmp = QImage(oimg.size(), oimg.format());
+// for(uint y = 0; y < tmp.height(); y++)
+// memcpy(tmp.bits()+y*tmp.bytesPerLine(), oimg.bits()+y*oimg.bytesPerLine(), tmp.bytesPerLine());
+// QDir dir("./");
+// dir.remove("test.png");
+// tmp.save("test.png");
+// }
+// qDebug() << "resize finished.";
+
+ return oimg;
+}
diff --git a/zimg/qzimg.h b/zimg/qzimg.h
new file mode 100644
index 00000000..d944fac6
--- /dev/null
+++ b/zimg/qzimg.h
@@ -0,0 +1,52 @@
+#ifndef QZIMG_H
+#define QZIMG_H
+
+#include
+
+class QZimgPrivate;
+
+class QZimg : public QObject
+{
+ Q_OBJECT
+public:
+ enum FilterMode {
+ ResizePoint,
+ ResizeBicubic,
+ ResizeSpline16,
+ ResizeSpline36,
+ ResizeLanczos,
+ };
+ Q_ENUM(FilterMode)
+
+
+ explicit QZimg(QObject *parent = 0);
+ ~QZimg();
+
+ /**
+ * @brief createPackedImage zimg must require 64bit packed memory bitmap
+ * @param size of new image
+ * @param fmt of new image(only Format_Grayscale8, Format_RGB888, Format_ARGB32)
+ * @param stridePack packed byte size for each line(64 bytes aligned, or 64x4 bytes aligned for Format_ARGB32)
+ * @return a image which have 64byte aligned stride bytes for each line
+ */
+ static QImage createPackedImage(QSize size, QImage::Format fmt, int stridePack=64);
+
+ /**
+ * @brief stridePackedImage
+ * @param src
+ * @param stridePack
+ * @return a image which have 64byte aligned stride bytes for each line
+ */
+ static QImage toPackedImage(const QImage& src, int stridePack=64);
+
+ static QImage scaled(const QImage& src, const QSize& s, Qt::AspectRatioMode aspectMode = Qt::IgnoreAspectRatio,
+ FilterMode mode = ResizeBicubic);
+
+signals:
+
+public slots:
+private:
+ QZimgPrivate* d;
+};
+
+#endif // QZIMG_H
diff --git a/zimg/zimg b/zimg/zimg
new file mode 160000
index 00000000..5e603b63
--- /dev/null
+++ b/zimg/zimg
@@ -0,0 +1 @@
+Subproject commit 5e603b6390f0fc1e32e634dece083dd8b729334a
diff --git a/zimg/zimg.pro b/zimg/zimg.pro
new file mode 100644
index 00000000..13871dcf
--- /dev/null
+++ b/zimg/zimg.pro
@@ -0,0 +1,126 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2014-02-08T18:57:16
+#
+#-------------------------------------------------
+
+#QT -= core
+QT += core gui
+
+TARGET = zimg
+TEMPLATE = lib
+CONFIG += staticlib
+CONFIG += warn_off
+CONFIG += c++11
+
+DEFINES += ZIMG_X86
+
+equals(QMAKE_CC,"cl") {
+ QMAKE_CXXFLAGS += /wd4819 /wd4996
+ !CONFIG(debug, debug|release) {
+ QMAKE_CXXFLAGS += /GL /W3 /Gy /Gm- /Gd /Oi
+ }
+}
+
+
+SOURCES += \
+ $$PWD/zimg/src/zimg/api/zimg.cpp \
+ $$PWD/zimg/src/zimg/colorspace/colorspace.cpp \
+ $$PWD/zimg/src/zimg/colorspace/colorspace_param.cpp \
+ $$PWD/zimg/src/zimg/colorspace/gamma.cpp \
+ $$PWD/zimg/src/zimg/colorspace/graph.cpp \
+ $$PWD/zimg/src/zimg/colorspace/matrix3.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_avx.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_avx2.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_sse.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_sse2.cpp \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_x86.cpp \
+ $$PWD/zimg/src/zimg/common/cpuinfo.cpp \
+ $$PWD/zimg/src/zimg/common/libm_wrapper.cpp \
+ $$PWD/zimg/src/zimg/common/matrix.cpp \
+ $$PWD/zimg/src/zimg/common/x86util.cpp \
+ $$PWD/zimg/src/zimg/depth/depth.cpp \
+ $$PWD/zimg/src/zimg/depth/depth_convert.cpp \
+ $$PWD/zimg/src/zimg/depth/depth_convert_avx2.cpp \
+ $$PWD/zimg/src/zimg/depth/depth_convert_sse2.cpp \
+ $$PWD/zimg/src/zimg/depth/depth_convert_x86.cpp \
+ $$PWD/zimg/src/zimg/depth/dither.cpp \
+ $$PWD/zimg/src/zimg/depth/dither_avx2.cpp \
+ $$PWD/zimg/src/zimg/depth/dither_sse2.cpp \
+ $$PWD/zimg/src/zimg/depth/dither_x86.cpp \
+ $$PWD/zimg/src/zimg/depth/error_diffusion_avx2.cpp \
+ $$PWD/zimg/src/zimg/depth/error_diffusion_sse2.cpp \
+ $$PWD/zimg/src/zimg/depth/f16c_ivb.cpp \
+ $$PWD/zimg/src/zimg/depth/f16c_sse2.cpp \
+ $$PWD/zimg/src/zimg/depth/quantize.cpp \
+ $$PWD/zimg/src/zimg/graph/basic_filter.cpp \
+ $$PWD/zimg/src/zimg/graph/filtergraph.cpp \
+ $$PWD/zimg/src/zimg/graph/graphbuilder.cpp \
+ $$PWD/zimg/src/zimg/resize/filter.cpp \
+ $$PWD/zimg/src/zimg/resize/resize.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl_avx.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl_avx2.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl_sse.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl_sse2.cpp \
+ $$PWD/zimg/src/zimg/resize/resize_impl_x86.cpp \
+ $$PWD/zimg/src/zimg/unresize/bilinear.cpp \
+ $$PWD/zimg/src/zimg/unresize/unresize.cpp \
+ $$PWD/zimg/src/zimg/unresize/unresize_impl.cpp \
+ qzimg.cpp
+
+HEADERS += \
+ $$PWD/zimg/src/zimg/api/zimg.h \
+ $$PWD/zimg/src/zimg/api/zimg++.hpp \
+ $$PWD/zimg/src/zimg/colorspace/colorspace.h \
+ $$PWD/zimg/src/zimg/colorspace/colorspace_param.h \
+ $$PWD/zimg/src/zimg/colorspace/gamma.h \
+ $$PWD/zimg/src/zimg/colorspace/graph.h \
+ $$PWD/zimg/src/zimg/colorspace/matrix3.h \
+ $$PWD/zimg/src/zimg/colorspace/operation.h \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl.h \
+ $$PWD/zimg/src/zimg/colorspace/operation_impl_x86.h \
+ $$PWD/zimg/src/zimg/common/align.h \
+ $$PWD/zimg/src/zimg/common/alloc.h \
+ $$PWD/zimg/src/zimg/common/builder.h \
+ $$PWD/zimg/src/zimg/common/ccdep.h \
+ $$PWD/zimg/src/zimg/common/checked_int.h \
+ $$PWD/zimg/src/zimg/common/cpuinfo.h \
+ $$PWD/zimg/src/zimg/common/except.h \
+ $$PWD/zimg/src/zimg/common/libm_wrapper.h \
+ $$PWD/zimg/src/zimg/common/make_unique.h \
+ $$PWD/zimg/src/zimg/common/matrix.h \
+ $$PWD/zimg/src/zimg/common/pixel.h \
+ $$PWD/zimg/src/zimg/common/static_map.h \
+ $$PWD/zimg/src/zimg/common/x86util.h \
+ $$PWD/zimg/src/zimg/common/zassert.h \
+ $$PWD/zimg/src/zimg/depth/depth.h \
+ $$PWD/zimg/src/zimg/depth/depth_convert.h \
+ $$PWD/zimg/src/zimg/depth/depth_convert_x86.h \
+ $$PWD/zimg/src/zimg/depth/dither.h \
+ $$PWD/zimg/src/zimg/depth/dither_x86.h \
+ $$PWD/zimg/src/zimg/depth/f16c_x86.h \
+ $$PWD/zimg/src/zimg/depth/hexfloat.h \
+ $$PWD/zimg/src/zimg/depth/quantize.h \
+ $$PWD/zimg/src/zimg/graph/basic_filter.h \
+ $$PWD/zimg/src/zimg/graph/filtergraph.h \
+ $$PWD/zimg/src/zimg/graph/graphbuilder.h \
+ $$PWD/zimg/src/zimg/graph/image_buffer.h \
+ $$PWD/zimg/src/zimg/graph/image_filter.h \
+ $$PWD/zimg/src/zimg/resize/filter.h \
+ $$PWD/zimg/src/zimg/resize/resize.h \
+ $$PWD/zimg/src/zimg/resize/resize_impl.h \
+ $$PWD/zimg/src/zimg/resize/resize_impl_x86.h \
+ $$PWD/zimg/src/zimg/unresize/bilinear.h \
+ $$PWD/zimg/src/zimg/unresize/unresize.h \
+ $$PWD/zimg/src/zimg/unresize/unresize_impl.h \
+ $$PWD/zimg/src/testcommon/aligned_malloc.h \
+ qzimg.h
+
+INCLUDEPATH += \
+ $$PWD/zimg/src/zimg $$PWD/zimg/src/testcommon
+
+DESTDIR = ../lib
+