11#include <QMutexLocker>
14#include <ksanecore_debug.h>
19ScanThread::ScanThread(SANE_Handle handle):
20 QThread(), m_saneHandle(handle), m_imageBuilder(&m_image, &m_dpi)
22 m_emitProgressUpdateTimer.setSingleShot(
false);
23 m_emitProgressUpdateTimer.setInterval(500);
29void ScanThread::setImageInverted(
const QVariant &newValue)
31 const bool newInvert = newValue.
toBool();
32 if (m_invertColors != newInvert) {
33 m_invertColors = newInvert;
34 m_image.invertPixels();
38void ScanThread::setImageResolution(
const QVariant &newValue)
41 const int newDPI = newValue.
toInt(&ok);
42 if (ok && m_dpi != newDPI) {
47ScanThread::ReadStatus ScanThread::frameStatus()
52SANE_Status ScanThread::saneStatus()
57QImage *ScanThread::scanImage()
62void ScanThread::lockScanImage()
67void ScanThread::unlockScanImage()
69 m_imageMutex.unlock();
72void ScanThread::cancelScan()
74 m_readStatus = ReadCancel;
80 m_readStatus = ReadOngoing;
81 m_announceFirstRead =
true;
84 m_saneStatus = sane_start(m_saneHandle);
86 if (m_readStatus == ReadCancel) {
90 if (m_saneStatus != SANE_STATUS_GOOD) {
91 qCDebug(KSANECORE_LOG) <<
"sane_start=" << sane_strstatus(m_saneStatus);
92 sane_cancel(m_saneHandle);
93 m_readStatus = ReadError;
98 m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
99 if (m_saneStatus != SANE_STATUS_GOOD) {
100 qCDebug(KSANECORE_LOG) <<
"sane_get_parameters=" << sane_strstatus(m_saneStatus);
101 sane_cancel(m_saneHandle);
102 m_readStatus = ReadError;
107 m_frameSize = m_params.lines * m_params.bytes_per_line;
108 if ((m_params.format == SANE_FRAME_RED) ||
109 (m_params.format == SANE_FRAME_GREEN) ||
110 (m_params.format == SANE_FRAME_BLUE)) {
112 m_dataSize = m_frameSize * 3;
114 m_dataSize = m_frameSize;
117 m_imageBuilder.start(m_params);
121 while (m_readStatus == ReadOngoing) {
126void ScanThread::updateScanProgress()
129 if (m_dataSize <= 0) {
135 if (m_frameSize < m_dataSize) {
136 bytesRead = m_frameRead + (m_frameSize * m_frame_t_count);
138 bytesRead = m_frameRead;
142 Q_EMIT scanProgressUpdated(
static_cast<int>((
static_cast<float>(bytesRead) * 100.0) / m_dataSize));
146void ScanThread::readData()
148 SANE_Int readBytes = 0;
149 m_saneStatus = sane_read(m_saneHandle, m_readData, SCAN_READ_CHUNK_SIZE, &readBytes);
151 if (readBytes > 0 && m_announceFirstRead) {
152 Q_EMIT scanProgressUpdated(0);
153 m_announceFirstRead =
false;
156 switch (m_saneStatus) {
157 case SANE_STATUS_GOOD:
161 case SANE_STATUS_EOF:
163 if (m_frameRead < m_frameSize) {
164 qCDebug(KSANECORE_LOG) <<
"frameRead =" << m_frameRead <<
", frameSize =" << m_frameSize <<
"readBytes =" << readBytes;
165 if ((readBytes > 0) && ((m_frameRead + readBytes) <= m_frameSize)) {
166 qCDebug(KSANECORE_LOG) <<
"This is not a standard compliant backend";
167 copyToScanData(readBytes);
170 if (m_params.depth == 1 && m_params.lines > 0 && m_params.lines * m_params.pixels_per_line <= m_frameRead * 8) {
171 qCDebug(KSANECORE_LOG) <<
"Warning!! This backend seems to return wrong bytes_per_line for line-art images!";
172 qCDebug(KSANECORE_LOG) <<
"Warning!! Trying to correct the value!";
173 m_params.bytes_per_line = m_frameRead / m_params.lines;
175 m_readStatus = ReadReady;
178 if (m_params.last_frame == SANE_TRUE) {
180 m_imageBuilder.cropImagetoSize();
181 m_readStatus = ReadReady;
185 m_saneStatus = sane_start(m_saneHandle);
186 if (m_saneStatus != SANE_STATUS_GOOD) {
187 qCDebug(KSANECORE_LOG) <<
"sane_start =" << sane_strstatus(m_saneStatus);
188 m_readStatus = ReadError;
191 m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
192 if (m_saneStatus != SANE_STATUS_GOOD) {
193 qCDebug(KSANECORE_LOG) <<
"sane_get_parameters =" << sane_strstatus(m_saneStatus);
194 m_readStatus = ReadError;
195 sane_cancel(m_saneHandle);
199 m_imageBuilder.beginFrame(m_params);
205 qCDebug(KSANECORE_LOG) <<
"sane_read=" << m_saneStatus <<
"=" << sane_strstatus(m_saneStatus);
206 m_readStatus = ReadError;
207 sane_cancel(m_saneHandle);
211 copyToScanData(readBytes);
214void ScanThread::copyToScanData(
int readBytes)
216 if (m_invertColors) {
217 if (m_params.depth == 16) {
219 quint16 *u16ptr =
reinterpret_cast<quint16 *
>(m_readData);
220 for (
int i = 0; i < readBytes / 2; i++) {
221 u16ptr[i] = 0xFFFF - u16ptr[i];
223 }
else if (m_params.depth == 8) {
224 for (
int i = 0; i < readBytes; i++) {
225 m_readData[i] = 0xFF - m_readData[i];
227 }
else if (m_params.depth == 1) {
228 for (
int i = 0; i < readBytes; i++) {
229 m_readData[i] = ~m_readData[i];
235 if (m_imageBuilder.copyToImage(m_readData, readBytes)) {
236 m_frameRead += readBytes;
238 m_readStatus = ReadError;
244#include "moc_scanthread.cpp"
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool toBool() const const
int toInt(bool *ok) const const