1/* -*- C++ -*-
2 This file is part of ThreadWeaver.
3
4 SPDX-FileCopyrightText: 2005-2014 Mirko Boehm <mirko@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include <QBuffer>
10#include <QFile>
11#include <QFileInfo>
12#include <QImageReader>
13#include <QLocale>
14#include <QtDebug>
15
16#include <ThreadWeaver/Exception>
17#include <ThreadWeaver/ThreadWeaver>
18
19#include "Image.h"
20#include "Model.h"
21
22// const int Image::ThumbHeight = 75;
23// const int Image::ThumbWidth = 120;
24const int Image::ThumbHeight = 60;
25const int Image::ThumbWidth = 80;
26QReadWriteLock Image::Lock;
27int Image::ProcessingOrder;
28
29Image::Image(const QString inputFileName, const QString outputFileName, Model *model, int id)
30 : m_inputFileName(inputFileName)
31 , m_outputFileName(outputFileName)
32 , m_model(model)
33 , m_id(id)
34{
35}
36
37Progress Image::progress() const
38{
39 return qMakePair(value1: m_progress.loadRelaxed(), value2: Step_NumberOfSteps);
40}
41
42QString Image::description() const
43{
44 QReadLocker l(&Lock);
45 return m_description;
46}
47
48QString Image::details() const
49{
50 QReadLocker l(&Lock);
51 return m_details;
52}
53
54QString Image::details2() const
55{
56 QReadLocker l(&Lock);
57 return m_details2;
58}
59
60int Image::processingOrder() const
61{
62 return m_processingOrder.loadAcquire();
63}
64
65const QString Image::inputFileName() const
66{
67 return m_inputFileName;
68}
69
70const QString Image::outputFileName() const
71{
72 return m_outputFileName;
73}
74
75QImage Image::thumbNail() const
76{
77 QReadLocker r(&Lock);
78 return m_thumbnail;
79}
80
81void Image::loadFile()
82{
83 m_processingOrder.storeRelease(newValue: ProcessingOrder++);
84 QFile file(m_inputFileName);
85 if (!file.open(flags: QIODevice::ReadOnly)) {
86 error(step: Step_LoadFile, message: tr(sourceText: "Unable to load input file!"));
87 }
88 m_imageData = file.readAll();
89 QFileInfo fi(file);
90 QLocale locale;
91 QString details2 = tr(sourceText: "%1kB").arg(a: locale.toString(i: fi.size() / 1024));
92 {
93 QWriteLocker l(&Lock);
94 m_description = fi.fileName();
95 m_details2 = details2;
96 }
97 announceProgress(step: Step_LoadFile);
98}
99
100void Image::loadImage()
101{
102 m_processingOrder.storeRelease(newValue: ProcessingOrder++);
103 QBuffer in(&m_imageData);
104 in.open(openMode: QIODevice::ReadOnly);
105 QImageReader reader(&in);
106 m_image = reader.read();
107 m_imageData.clear();
108 if (m_image.isNull()) {
109 QWriteLocker l(&Lock);
110 m_details = tr(sourceText: "%1!").arg(a: reader.errorString());
111 error(step: Step_LoadImage, message: m_details);
112 }
113 QString details = tr(sourceText: "%1x%2 pixels").arg(a: m_image.width()).arg(a: m_image.height());
114 {
115 QWriteLocker l(&Lock);
116 m_details = details;
117 }
118 announceProgress(step: Step_LoadImage);
119}
120
121void Image::computeThumbNail()
122{
123 m_processingOrder.storeRelease(newValue: ProcessingOrder++);
124 QImage thumb = m_image.scaled(w: ThumbWidth, h: ThumbHeight, aspectMode: Qt::KeepAspectRatioByExpanding, mode: Qt::SmoothTransformation);
125 if (thumb.isNull()) {
126 error(step: Step_ComputeThumbNail, message: tr(sourceText: "Unable to compute thumbnail!"));
127 }
128 { // thumb is implicitly shared, no copy:
129 QWriteLocker l(&Lock);
130 m_thumbnail = thumb;
131 }
132
133 m_image = QImage();
134 announceProgress(step: Step_ComputeThumbNail);
135}
136
137void Image::saveThumbNail()
138{
139 QImage thumb;
140 {
141 QReadLocker r(&Lock);
142 thumb = m_thumbnail;
143 }
144 if (!thumb.save(fileName: m_outputFileName)) {
145 error(step: Step_SaveThumbNail, message: tr(sourceText: "Unable to save output file!"));
146 }
147 announceProgress(step: Step_SaveThumbNail);
148}
149
150void Image::announceProgress(Steps step)
151{
152 m_progress.storeRelease(newValue: step);
153 if (m_model) {
154 m_model->progressChanged();
155 m_model->elementChanged(id: m_id);
156 }
157}
158
159void Image::error(Image::Steps step, const QString &message)
160{
161 m_failedStep.storeRelaxed(newValue: step);
162 announceProgress(step: Step_Complete);
163 throw ThreadWeaver::JobFailed(message);
164}
165

source code of threadweaver/examples/ThumbNailer/Image.cpp