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 @@ - &Sort + &Sort - ItemContext + ItemContext @@ -130,8 +130,11 @@ QPushButton:hover { 24 + + Move to Home + - + Move to Home @@ -153,8 +156,11 @@ QPushButton:hover { 24 + + Prev + - + Prev @@ -176,8 +182,11 @@ QPushButton:hover { 24 + + Next + - + Next @@ -199,8 +208,11 @@ QPushButton:hover { 24 + + To parent folder + - + To parent folder @@ -222,8 +234,11 @@ QPushButton:hover { 24 + + Reload + - + Reload @@ -258,6 +273,9 @@ QPushButton:hover { true + + ChangeSorting + Name diff --git a/QuickViewer/src/imageview.cpp b/QuickViewer/src/imageview.cpp index 072454c9..d45fb332 100644 --- a/QuickViewer/src/imageview.cpp +++ b/QuickViewer/src/imageview.cpp @@ -98,39 +98,16 @@ bool ImageView::on_addImage_triggered(ImageContent ic, bool pageNext) if(m_pageManager == nullptr) return false; m_ptLeftTop.reset(); QGraphicsScene *s = scene(); + QSize size = ic.Image.size(); + PageContent pgi(this, s, ic); - - QSize size; - QPoint offset; - QGraphicsItem* gitem = nullptr; - int rotate = 0; - if(ic.BaseSize.width() > 0) { - QGraphicsPixmapItem* gpi = s->addPixmap(ic.Image); - gitem = gpi; - size = ic.Image.size(); - 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; - } - } - gpi->setRotation(rotate); - } else { - QGraphicsTextItem* gtext = s->addText(tr("NOT IMAGE")); - gtext->setDefaultTextColor(Qt::white); - //qDebug() << gtext; - gitem = gtext; - size = QSize(100, 100); - } - PageGraphicsItem pgi(ic, gitem, rotate); - if(pageNext) + if(pageNext) { m_pages.push_back(pgi); - else + connect(&(m_pages.last()), SIGNAL(resizeFinished()), this, SLOT(readyForPaint())); + } else { m_pages.push_front(pgi); + connect(&(m_pages.first()), SIGNAL(resizeFinished()), this, SLOT(readyForPaint())); + } m_effectManager.prepareInitialize(); @@ -155,12 +132,12 @@ void ImageView::readyForPaint() { int pageCount = m_pageManager->currentPage(); QRect sceneRect; for(int i = 0; i < m_pages.size(); i++) { - PageGraphicsItem::Fitting fitting = PageGraphicsItem::FitCenter; + PageContent::Fitting fitting = PageContent::FitCenter; QRect pageRect = QRect(QPoint(), viewport()->size()); if(m_pages.size() == 2) { fitting = ((i==0 && !qApp->RightSideBook()) || (i==1 && qApp->RightSideBook())) - ? PageGraphicsItem::FitRight : PageGraphicsItem::FitLeft; - pageRect = QRect(QPoint(fitting==PageGraphicsItem::FitRight ? 0 : pageRect.width()/2, 0), QSize(pageRect.width()/2,pageRect.height())); + ? PageContent::FitRight : PageContent::FitLeft; + pageRect = QRect(QPoint(fitting==PageContent::FitRight ? 0 : pageRect.width()/2, 0), QSize(pageRect.width()/2,pageRect.height())); } QRect drawRect; if(qApp->Fitting()) { diff --git a/QuickViewer/src/imageview.h b/QuickViewer/src/imageview.h index 912ed041..4dcf1a56 100644 --- a/QuickViewer/src/imageview.h +++ b/QuickViewer/src/imageview.h @@ -8,6 +8,7 @@ #include "exifdialog.h" #include "models/pagemanager.h" #include "models/shadermanager.h" +#include "models/pagecontent.h" class SavedPoint : public QPoint { @@ -33,86 +34,6 @@ class SavedPoint : public QPoint QPoint m_ptSaved; }; -/** - * @brief The PageGraphicsItem struct - * contains the informations of a Page - */ -struct PageGraphicsItem -{ - ImageContent Ic; - /** - * @brief GrItem - * Page image is used as a QGraphicsItem. it will be registed to the scene - */ - QGraphicsItem* GrItem; - /** - * @brief Rotate: rotation as digrees - */ - int Rotate; - enum Fitting { - FitCenter, - FitLeft, - FitRight - }; - PageGraphicsItem() - : Ic(), GrItem(nullptr), Rotate(0){} - PageGraphicsItem(ImageContent ic, QGraphicsItem* item, int rotate) - : Ic(ic), GrItem(item), Rotate(rotate){} - PageGraphicsItem(const PageGraphicsItem& rhs) - : Ic(rhs.Ic), GrItem(rhs.GrItem), Rotate(rhs.Rotate) {} - QPoint Offset(int rotateOffset=0) { - 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 CurrentSize(int rotateOffset=0) { - int rot = (Rotate+rotateOffset) % 360; - return rot==90 || rot==270 ? QSize(Ic.Image.height(), Ic.Image.width()) : Ic.Image.size(); - } - - /** - * @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) { - QSize currentSize = CurrentSize(rotateOffset); - QSize newsize = currentSize.scaled(viewport.size(), Qt::KeepAspectRatio); - qreal scale = 1.0*newsize.width()/currentSize.width(); - GrItem->setScale(scale); - QPoint of = Offset(rotateOffset); - of *= scale; - GrItem->setRotation(Rotate+rotateOffset); - 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); - GrItem->setPos(drawRect.topLeft()); - } else { // fitting on left and right - drawRect = QRect(QPoint(of.x() + viewport.x(), of.y() + (viewport.height()-newsize.height())/2), newsize); - GrItem->setPos(drawRect.topLeft()); - } - return drawRect; - } - QRect setPageLayoutManual(QRect viewport, Fitting fitting, qreal scale, int rotateOffset=0) { - QSize size = viewport.size(); - QSize currentSize = CurrentSize(rotateOffset); - QSize newsize = currentSize * scale; -// newsize *= scale; - GrItem->setScale(scale); - QPoint of = Offset(rotateOffset); - of *= scale; - GrItem->setRotation(Rotate+rotateOffset); - 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); - GrItem->setPos(drawRect.topLeft()); - return drawRect; - } -}; - /** * @brief The ImageView class * It provides to show 1 or 2 images once, using OpenGL. @@ -198,7 +119,7 @@ public slots: private: RendererType m_renderer; - QVector m_pages; + QVector m_pages; SavedPoint m_ptLeftTop; QGraphicsScene* m_scene; diff --git a/QuickViewer/src/mainwindow.cpp b/QuickViewer/src/mainwindow.cpp index 9ad8975f..a58a2c35 100644 --- a/QuickViewer/src/mainwindow.cpp +++ b/QuickViewer/src/mainwindow.cpp @@ -35,7 +35,8 @@ MainWindow::MainWindow(QWidget *parent) << ui->actionShaderNearestNeighbor << ui->actionShaderBilinear << ui->actionShaderBicubic - << ui->actionShaderLanczos; + << ui->actionShaderLanczos + << ui->actionShaderBilinearBeforeCpuBicubic; // setup checkable menus ui->actionFitting->setChecked(qApp->Fitting()); @@ -96,6 +97,7 @@ MainWindow::MainWindow(QWidget *parent) case qvEnums::Bilinear: ui->actionShaderBilinear->setChecked(true); break; case qvEnums::Bicubic: ui->actionShaderBicubic->setChecked(true); break; case qvEnums::Lanczos: ui->actionShaderLanczos->setChecked(true); break; + case qvEnums::BilinearAndCpuBicubic: ui->actionShaderBilinearBeforeCpuBicubic->setChecked(true); break; } @@ -546,13 +548,14 @@ void MainWindow::on_folderWindow_triggered() { if(m_folderWindow) { bool isChild = m_folderWindow->parent(); + QString oldpath = m_folderWindow->currentPath(); on_folderWindowClosed_triggered(); if(isChild) { m_folderWindow = new FolderWindow(nullptr, ui); QRect self = geometry(); m_folderWindow->setGeometry(self.left()-100, self.top()+100, self.width(), self.height()); m_folderWindow->setAsToplevelWindow(); - m_folderWindow->setFolderPath(m_pageManager.volumePath()); + m_folderWindow->setFolderPath(oldpath); connect(m_folderWindow, SIGNAL(closed()), this, SLOT(on_folderWindowClosed_triggered())); connect(m_folderWindow, SIGNAL(openVolume(QString)), this, SLOT(on_openVolumeByCatalog_triggered(QString))); connect(&m_pageManager, SIGNAL(volumeChanged(QString)), m_folderWindow, SLOT(on_volumeChanged_triggered(QString))); @@ -911,6 +914,14 @@ void MainWindow::on_shaderLanczos_triggered() ui->graphicsView->readyForPaint(); } +void MainWindow::on_shaderBilinearBeforeCpuBicubic_triggered() +{ + uncheckAllShaderMenus(); + qApp->setEffect(qvEnums::BilinearAndCpuBicubic); + ui->actionShaderBilinearBeforeCpuBicubic->setChecked(true); + ui->graphicsView->readyForPaint(); +} + void MainWindow::on_saveBookmark_triggered() { if(!m_pageManager.currentPageCount()) diff --git a/QuickViewer/src/mainwindow.h b/QuickViewer/src/mainwindow.h index 26ef4cd2..e6364601 100644 --- a/QuickViewer/src/mainwindow.h +++ b/QuickViewer/src/mainwindow.h @@ -111,6 +111,7 @@ public slots: void on_shaderBilinear_triggered(); void on_shaderBicubic_triggered(); void on_shaderLanczos_triggered(); + void on_shaderBilinearBeforeCpuBicubic_triggered(); // Bookmark void on_saveBookmark_triggered(); diff --git a/QuickViewer/src/mainwindow.ui b/QuickViewer/src/mainwindow.ui index dfb55aaa..77c859d2 100644 --- a/QuickViewer/src/mainwindow.ui +++ b/QuickViewer/src/mainwindow.ui @@ -308,6 +308,8 @@ + + @@ -680,7 +682,7 @@ true - &Bilinear interpolation (standard) + &Bilinear interpolation (fast) @@ -909,6 +911,14 @@ Show&Folder + + + true + + + CPU Bicubic after GPU Bilinear(standard) + + @@ -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 +