227 lines
5.4 KiB
C++
227 lines
5.4 KiB
C++
#include "imageringlist.h"
|
|
#include <QThreadPool>
|
|
#include <QDir>
|
|
#include <libraw/libraw.h>
|
|
#include <QDebug>
|
|
|
|
using namespace std;
|
|
|
|
const int DEFAULT_WIDTH = 3;
|
|
|
|
class LoadRunable : public QRunnable
|
|
{
|
|
QString m_file;
|
|
QObject *m_receiver;
|
|
public:
|
|
LoadRunable(const QString &file, QObject *receiver) :
|
|
m_file(file),
|
|
m_receiver(receiver)
|
|
{
|
|
}
|
|
void run()
|
|
{
|
|
if(m_file.endsWith(".CR2", Qt::CaseInsensitive))
|
|
{
|
|
LibRaw raw;
|
|
raw.open_file(m_file.toLocal8Bit().data());
|
|
raw.imgdata.params.half_size = true;
|
|
raw.imgdata.params.use_camera_wb = true;
|
|
raw.imgdata.params.user_flip = 0;
|
|
raw.unpack();
|
|
raw.dcraw_process();
|
|
libraw_processed_image_t *rawImg = raw.dcraw_make_mem_image();
|
|
QImage img(rawImg->width, rawImg->height, QImage::Format_RGB888);
|
|
qDebug() << rawImg->width << img.width()*3 << img.scanLine(1)-img.scanLine(0);
|
|
uint scanLine = rawImg->width*rawImg->colors;
|
|
for(uint i=0; i<rawImg->height; i++)
|
|
{
|
|
memcpy(img.scanLine(i), rawImg->data+(i*scanLine), scanLine);
|
|
}
|
|
raw.dcraw_clear_mem(rawImg);
|
|
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(QImage, img));
|
|
}
|
|
else
|
|
{
|
|
QImage img(m_file);
|
|
QMetaObject::invokeMethod(m_receiver, "imageLoaded", Qt::QueuedConnection, Q_ARG(QImage, img));
|
|
}
|
|
}
|
|
};
|
|
|
|
Image::Image(const QString name) :
|
|
m_loading(false),
|
|
m_released(true),
|
|
m_name(name)
|
|
{
|
|
}
|
|
|
|
void Image::load()
|
|
{
|
|
if(m_pixmap.isNull() && !m_loading)
|
|
{
|
|
m_loading = true;
|
|
m_released = false;
|
|
QThreadPool::globalInstance()->start(new LoadRunable(m_name, this));
|
|
}
|
|
if(!m_loading && !m_pixmap.isNull())
|
|
emit pixmapLoaded(this);
|
|
}
|
|
|
|
void Image::release()
|
|
{
|
|
m_pixmap = QPixmap();
|
|
m_released = true;
|
|
}
|
|
|
|
QString Image::name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
QPixmap Image::pixmap() const
|
|
{
|
|
return m_pixmap;
|
|
}
|
|
|
|
void Image::imageLoaded(QImage img)
|
|
{
|
|
m_loading = false;
|
|
if(!m_released)
|
|
{
|
|
m_pixmap = QPixmap::fromImage(img);
|
|
emit pixmapLoaded(this);
|
|
}
|
|
}
|
|
|
|
ImageRingList::ImageRingList(QObject *parent) : QObject(parent)
|
|
{
|
|
connect(&m_fileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(dirChanged(QString)));
|
|
}
|
|
|
|
bool ImageRingList::setDir(const QString path, const QString ¤tFile)
|
|
{
|
|
QDir dir(path);
|
|
|
|
if(dir.exists())
|
|
{
|
|
QStringList nameFilter;
|
|
nameFilter << "*.jpg" << "*.png" << "*.cr2";
|
|
|
|
QStringList list = dir.entryList(nameFilter, QDir::Files | QDir::Readable, QDir::Name);
|
|
QStringList absolutePaths;
|
|
foreach(const QString &file, list)
|
|
{
|
|
absolutePaths.append(dir.absoluteFilePath(file));
|
|
}
|
|
setFiles(absolutePaths, currentFile);
|
|
|
|
m_fileSystemWatcher.removePaths(m_fileSystemWatcher.directories());
|
|
m_fileSystemWatcher.addPath(path);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ImageRingList::setFile(const QString &file)
|
|
{
|
|
QFileInfo info(file);
|
|
setDir(info.absolutePath(), file);
|
|
}
|
|
|
|
ImagePtr ImageRingList::currentImage()
|
|
{
|
|
if(m_images.size())
|
|
return *m_currImage;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void ImageRingList::increment()
|
|
{
|
|
if(m_images.size())
|
|
{
|
|
(*m_firstImage)->release();
|
|
m_firstImage = increment(m_firstImage);
|
|
m_currImage = increment(m_currImage);
|
|
(*m_currImage)->load();
|
|
m_lastImage = increment(m_lastImage);
|
|
(*m_lastImage)->load();
|
|
}
|
|
}
|
|
|
|
void ImageRingList::decrement()
|
|
{
|
|
if(m_images.size())
|
|
{
|
|
(*m_lastImage)->release();
|
|
m_firstImage = decrement(m_firstImage);
|
|
m_currImage = decrement(m_currImage);
|
|
(*m_currImage)->load();
|
|
m_lastImage = decrement(m_lastImage);
|
|
(*m_firstImage)->load();
|
|
}
|
|
}
|
|
|
|
void ImageRingList::setFiles(const QStringList files, const QString ¤tFile)
|
|
{
|
|
m_images.clear();
|
|
foreach(const QString &file, files)
|
|
{
|
|
ImagePtr ptr = make_shared<Image>(file);
|
|
connect(ptr.get(), SIGNAL(pixmapLoaded(Image*)), this, SLOT(imageLoaded(Image*)));
|
|
m_images.append(ptr);
|
|
}
|
|
|
|
int index = files.indexOf(currentFile);
|
|
if(index < 0)
|
|
index = 0;
|
|
|
|
m_firstImage = m_currImage = m_lastImage = m_images.begin()+index;
|
|
(*m_currImage)->load();
|
|
|
|
m_width = DEFAULT_WIDTH<m_images.size()/2 ? DEFAULT_WIDTH : m_images.size()/2;
|
|
|
|
for(int i=0; i<m_width; i++)
|
|
{
|
|
m_firstImage = decrement(m_firstImage);
|
|
(*m_firstImage)->load();
|
|
m_lastImage = increment(m_lastImage);
|
|
(*m_lastImage)->load();
|
|
}
|
|
}
|
|
|
|
QList<ImagePtr>::iterator ImageRingList::increment(QList<ImagePtr>::iterator iter)
|
|
{
|
|
iter++;
|
|
if(iter == m_images.end())
|
|
iter = m_images.begin();
|
|
return iter;
|
|
}
|
|
|
|
QList<ImagePtr>::iterator ImageRingList::decrement(QList<ImagePtr>::iterator iter)
|
|
{
|
|
if(iter == m_images.begin())
|
|
iter = m_images.end();
|
|
iter--;
|
|
return iter;
|
|
}
|
|
|
|
void ImageRingList::imageLoaded(Image *image)
|
|
{
|
|
if(image->name() == (*m_currImage)->name())
|
|
{
|
|
emit pixmapLoaded(image->pixmap());
|
|
}
|
|
}
|
|
|
|
void ImageRingList::dirChanged(QString dir)
|
|
{
|
|
QString currentFile;
|
|
|
|
if(m_images.size())
|
|
currentFile = (*m_currImage)->name();
|
|
|
|
setDir(dir, currentFile);
|
|
emit currentImageChanged();
|
|
}
|