📄 imagecache.cpp
字号:
#include "imagecache.h"#include "../general/ndir.h"#include "../general/style.h"#include <libaimaging.h>#include <qdir.h>#include <qfileinfo.h>#include <qpainter.h>#include <unistd.h>#define THUMBS_CACHE_NAME ".arcthumb"#define THUMBS_EXTENSION ".ATC"#define THUMBS_VERSION 1#define THUMBS_WIDTH 196#define THUMBS_HEIGHT 128ImageCache::ImageCache(int entrycnt, const QSize &imgsize) : m_cache(entrycnt, entrycnt) , m_reader(NULL) , m_size(imgsize) , m_needs_caching(false) { m_cache.setAutoDelete(true); m_toload.setAutoDelete(true); connect(&m_loadt, SIGNAL(timeout()), this, SLOT(readLines()));}ImageCache::~ImageCache() { delete m_reader;}void ImageCache::setSize(const QSize &size) { m_size= size; m_cache.clear();}void ImageCache::clear() { m_cache.clear();}void ImageCache::setCapacity(int capacity) { m_cache.setMaxCost(capacity);}QImage* ImageCache::getImage(const QString &path) { QImage *img= m_cache.find(path); if(img == NULL) { img= loadImage(path, m_size); if(img != NULL) { if(!m_cache.insert(path, img, 1)) delete img; } } return img;}QImage* ImageCache::getImageAsync(const QString &path) { QImage *img= m_cache.find(path); if(img == NULL) { if(QFileInfo(path).isDir()) { return getImage(path); } else { m_toload.enqueue(new QString(path)); loadNextImageAsync(); return NULL; } } else { return img; }};void ImageCache::loadNextImageAsync() { if(m_toload.isEmpty()) return; if(m_reader != NULL) return; QString *path= m_toload.dequeue(); if(m_cache.find(*path) == NULL) { loadImageAsync(*path); } else { loadNextImageAsync(); } delete path;}void ImageCache::loadImageAsync(const QString &path) { m_curpath= path; delete m_reader; m_reader= NULL; AMemorySink *sink= new AMemorySink(); AFormatFilter *formatf= new AFormatFilter(sink, true); formatf->setTargetFormat(AImageConsumer::RGBA); AScaleFilter *scalef= new AScaleFilter(formatf, true); scalef->setTargetSize(QSize(m_size.width(), m_size.height() - 1), true); if(m_size.width() <= THUMBS_WIDTH && m_size.height() <= THUMBS_HEIGHT) { // try to read thumbnail if(path.startsWith("/media")) { m_reader= new ArcThumbReader(NULL, false); if(!m_reader->setFileSource(path.utf8())) { delete m_reader; m_reader= NULL; } } m_reader= new AExifReader(AImageConsumer::RGB, NULL, false); if(!m_reader->setFileSource(path.utf8())) { delete m_reader; m_reader= NULL; } } if(m_reader == NULL) { m_reader= AImageReader::createReaderFor(path.utf8(), AImageConsumer::RGB); m_needs_caching= true; } QSize imgsize; if(m_reader != NULL) { m_reader->setConsumer(scalef, true); imgsize= m_reader->imageSize(); float xfak= float(m_size.width())/ imgsize.width(); float yfak= float(m_size.height() - 1)/ imgsize.height(); float fak= QMIN(xfak, yfak); imgsize.setWidth(int(imgsize.width()* fak)); imgsize.setHeight(int(imgsize.height()* fak)); } else {// if(QFileInfo(path).isDir())// createFolderImage(path, m_size); } QImage *img= new QImage(m_size, 32); img->fill(0); m_cache.insert(path, img, 1); if(m_reader != NULL) { int xofs= (m_size.width() - imgsize.width())/ 2; int yofs= (m_size.height() - imgsize.height())/ 2; xofs= QMAX(xofs, 0); yofs= QMAX(yofs, 0); sink->setTarget(img->scanLine(yofs) + xofs* 4, img->bytesPerLine()); m_loadt.start(0, true); } else { delete scalef; }}void ImageCache::readLines() { if(m_reader == NULL) return; int read= m_reader->readLines(64); if(read == 64) { m_loadt.start(0, true); } else { emit imageRead(); delete m_reader; m_reader= NULL;// if(m_needs_caching) writeThumbnail(m_curpath); loadNextImageAsync(); }}QImage* ImageCache::loadImage(const QString &path, const QSize &size) { AMemorySink sink; AFormatFilter formatf(&sink, false); formatf.setTargetFormat(AImageConsumer::RGBA); AScaleFilter scalef(&formatf, false); scalef.setTargetSize(QSize(size.width(), size.height() - 1), true); AImageReader *reader= AImageReader::createReaderFor(path.utf8(), AImageConsumer::RGB); QSize imgsize; if(reader == NULL) { if(QFileInfo(path).isDir()) return createFolderImage(path, size); } else { reader->setConsumer(&scalef, false); reader->setMinimumTargetSize(m_size); imgsize= reader->imageSize(); float xfak= float(size.width())/ imgsize.width(); float yfak= float(size.height() - 1)/ imgsize.height(); float fak= QMIN(xfak, yfak); imgsize.setWidth(int(imgsize.width()* fak)); imgsize.setHeight(int(imgsize.height()* fak)); } QImage *img= new QImage(size, 32); img->fill(0); if(reader != NULL) { int xofs= (size.width() - imgsize.width())/ 2; int yofs= (size.height() - imgsize.height())/ 2; xofs= QMAX(xofs, 0); yofs= QMAX(yofs, 0); sink.setTarget(img->scanLine(yofs) + xofs* 4, img->bytesPerLine()); reader->read(); delete reader; } return img;}QImage* ImageCache::createFolderImage(const QString &path, const QSize &size) { QImage *folderi= getImage(AStyle::iconpath + "/docicons/iconfolder.png"); int w= size.width(); int h= size.height(); NDir dir(NULL); dir.setPath(path); if(dir.count() > 0) { QString path= dir.pathAt(0); QFileInfo fi(path); if(!fi.isDir()) { QImage *contenti= loadImage(path, QSize(w/ 2 - 2, h/ 2 - 4)); QPixmap pm(m_size); { QPainter p(&pm); p.drawImage(0, 0, *folderi); p.drawImage(w/ 4 + 2, h/ 3 + 4, *contenti); } QImage *res= new QImage(pm.convertToImage()); delete contenti; return res; } } return new QImage(*folderi);}void ImageCache::writeThumbnail(const QString &m_path) const { QImage *img= m_cache.find(m_path); if(img == NULL) return; // try to create target dir if necessary QFileInfo fi(m_path); if(fi.dirPath().startsWith("/media")) { QString thumbsdir(fi.dirPath() + "/" + THUMBS_CACHE_NAME); if(!QFileInfo(thumbsdir).exists()) { if(!QDir().mkdir(thumbsdir)); return; } QFile thumbf(thumbsdir + "/" + fi.baseName() + THUMBS_EXTENSION); if(thumbf.open(IO_WriteOnly)) { QDataStream dout(&thumbf); dout << fi.lastModified(); dout << img->width() << img->height(); dout << THUMBS_VERSION; int bpr= img->width()* sizeof(ushort); for(int y= 0; y < img->height(); y++) dout.writeRawBytes((const char*) img->scanLine(y), bpr); thumbf.close(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -