• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegraphics API Reference
  • KDE Home
  • Contact Us
 

libs/libksane/libksane

  • sources
  • kde-4.14
  • kdegraphics
  • libs
  • libksane
  • libksane
ksane_scan_thread.cpp
Go to the documentation of this file.
1 /* ============================================================
2 *
3 * This file is part of the KDE project
4 *
5 * Date : 2009-11-13
6 * Description : Sane interface for KDE
7 *
8 * Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) version 3, or any
14 * later version accepted by the membership of KDE e.V. (or its
15 * successor approved by the membership of KDE e.V.), which shall
16 * act as a proxy defined in Section 6 of version 3 of the license.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 * ============================================================ */
27 
28 // Local includes
29 #include "ksane_scan_thread.moc"
30 
31 #include <KDebug>
32 
33 namespace KSaneIface
34 {
35 
36 
37  KSaneScanThread::KSaneScanThread(SANE_Handle handle, QByteArray *data):
38  QThread(),
39  m_data(data),
40  m_saneHandle(handle),
41  m_frameSize(0),
42  m_frameRead(0),
43  m_frame_t_count(0),
44  m_dataSize(0),
45  m_saneStatus(SANE_STATUS_GOOD),
46  m_readStatus(READ_READY),
47  m_invertColors(false),
48  m_saneStartDone(false)
49  {}
50 
51  void KSaneScanThread::setImageInverted(bool inverted)
52  {
53  m_invertColors = inverted;
54  }
55 
56  SANE_Status KSaneScanThread::saneStatus()
57  {
58  return m_saneStatus;
59  }
60 
61  KSaneScanThread::ReadStatus KSaneScanThread::frameStatus()
62  {
63  return m_readStatus;
64  }
65 
66  void KSaneScanThread::cancelScan()
67  {
68  m_readStatus = READ_CANCEL;
69  }
70 
71  int KSaneScanThread::scanProgress()
72  {
73  if (m_dataSize == 0) return 0;
74 
75  int bytesRead;
76 
77  if (m_frameSize < m_dataSize) {
78  bytesRead = m_frameRead + (m_frameSize * m_frame_t_count);
79  }
80  else {
81  bytesRead = m_frameRead;
82  }
83  return (int)(((float)bytesRead * 100.0)/m_dataSize);
84  }
85 
86  SANE_Parameters KSaneScanThread::saneParameters()
87  {
88  return m_params;
89  }
90 
91  void KSaneScanThread::run()
92  {
93  m_dataSize = 0;
94  m_readStatus = READ_ON_GOING;
95  m_saneStartDone = false;
96 
97  // Start the scanning with sane_start
98  m_saneStatus = sane_start(m_saneHandle);
99 
100  m_saneStartDone = true;
101 
102  if (m_readStatus == READ_CANCEL) {
103  return;
104  }
105 
106  if (m_saneStatus != SANE_STATUS_GOOD) {
107  kDebug() << "sane_start=" << sane_strstatus(m_saneStatus);
108  m_readStatus = READ_ERROR;
109  // oneFinalScanDone() does the sane_cancel()
110  return;
111  }
112 
113  // Read image parameters
114  m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
115  if (m_saneStatus != SANE_STATUS_GOOD) {
116  kDebug() << "sane_get_parameters=" << sane_strstatus(m_saneStatus);
117  m_readStatus = READ_ERROR;
118  // oneFinalScanDone() does the sane_cancel()
119  return;
120  }
121 
122  // calculate data size
123  m_frameSize = m_params.lines * m_params.bytes_per_line;
124  if ((m_params.format == SANE_FRAME_RED) ||
125  (m_params.format == SANE_FRAME_GREEN) ||
126  (m_params.format == SANE_FRAME_BLUE))
127  {
128  m_dataSize = m_frameSize*3;
129  }
130  else {
131  m_dataSize = m_frameSize;
132  }
133 
134  m_data->clear();
135  if (m_dataSize > 0) {
136  m_data->reserve(m_dataSize);
137  }
138 
139  m_frameRead = 0;
140  m_frame_t_count = 0;
141  m_readStatus = READ_ON_GOING;
142  while (m_readStatus == READ_ON_GOING) {
143  readData();
144  }
145  }
146 
147  void KSaneScanThread::readData()
148  {
149  SANE_Int readBytes = 0;
150  m_saneStatus = sane_read(m_saneHandle, m_readData, SCAN_READ_CHUNK_SIZE, &readBytes);
151 
152  switch (m_saneStatus)
153  {
154  case SANE_STATUS_GOOD:
155  // continue to parsing the data
156  break;
157 
158  case SANE_STATUS_EOF:
159  if (m_frameRead < m_frameSize) {
160  kDebug() << "frameRead =" << m_frameRead << ", frameSize =" << m_frameSize << "readBytes =" << readBytes;
161  if ((readBytes > 0) && ((m_frameRead + readBytes) <= m_frameSize)) {
162  kDebug() << "This is not a standard compliant backend";
163  copyToScanData(readBytes);
164  }
165  m_readStatus = READ_READY; // It is better to return a broken image than nothing
166  return;
167  }
168  if (m_params.last_frame == SANE_TRUE) {
169  // this is where it all ends well :)
170  m_readStatus = READ_READY;
171  return;
172  }
173  else {
174  // start reading next frame
175  m_saneStatus = sane_start(m_saneHandle);
176  if (m_saneStatus != SANE_STATUS_GOOD) {
177  kDebug() << "sane_start =" << sane_strstatus(m_saneStatus);
178  m_readStatus = READ_ERROR;
179  return;
180  }
181  m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
182  if (m_saneStatus != SANE_STATUS_GOOD) {
183  kDebug() << "sane_get_parameters =" << sane_strstatus(m_saneStatus);
184  m_readStatus = READ_ERROR;
185  sane_cancel(m_saneHandle);
186  return;
187  }
188  //kDebug() << "New Frame";
189  m_frameRead = 0;
190  m_frame_t_count++;
191  break;
192  }
193  default:
194  kDebug() << "sane_read=" << m_saneStatus << "=" << sane_strstatus(m_saneStatus);
195  m_readStatus = READ_ERROR;
196  sane_cancel(m_saneHandle);
197  return;
198  }
199 
200  copyToScanData(readBytes);
201  }
202 
203  #define index_red8_to_rgb8(i) (i*3)
204  #define index_red16_to_rgb16(i) ((i/2)*6 + i%2)
205 
206  #define index_green8_to_rgb8(i) (i*3 + 1)
207  #define index_green16_to_rgb16(i) ((i/2)*6 + i%2 + 2)
208 
209  #define index_blue8_to_rgb8(i) (i*3 + 2)
210  #define index_blue16_to_rgb16(i) ((i/2)*6 + i%2 + 4)
211 
212  void KSaneScanThread::copyToScanData(int readBytes)
213  {
214  if (m_invertColors) {
215  if (m_params.depth == 16) {
216  //if (readBytes%2) qDebug() << "readBytes=" << readBytes;
217  quint16 *u16ptr = reinterpret_cast<quint16*>(m_readData);
218  for(int i=0; i<readBytes/2; i++) {
219  u16ptr[i] = 0xFFFF - u16ptr[i];
220  }
221  }
222  else if (m_params.depth == 8) {
223  for(int i=0; i<readBytes; i++) {
224  m_readData[i] = 0xFF - m_readData[i];
225  }
226  }
227  else if (m_params.depth == 1) {
228  for(int i=0; i<readBytes; i++) {
229  m_readData[i] = ~m_readData[i];
230  }
231  }
232  }
233  switch (m_params.format)
234  {
235  case SANE_FRAME_GRAY:
236  m_data->append((const char*)m_readData, readBytes);
237  m_frameRead += readBytes;
238  return;
239  case SANE_FRAME_RGB:
240  if (m_params.depth == 1) {
241  break;
242  }
243  m_data->append((const char*)m_readData, readBytes);
244  m_frameRead += readBytes;
245  return;
246 
247  case SANE_FRAME_RED:
248  if (m_params.depth == 8) {
249  for (int i=0; i<readBytes; i++) {
250  (*m_data)[index_red8_to_rgb8(m_frameRead)] = m_readData[i];
251  m_frameRead++;
252  }
253  return;
254  }
255  else if (m_params.depth == 16) {
256  for (int i=0; i<readBytes; i++) {
257  (*m_data)[index_red16_to_rgb16(m_frameRead)] = m_readData[i];
258  m_frameRead++;
259  }
260  return;
261  }
262  break;
263 
264  case SANE_FRAME_GREEN:
265  if (m_params.depth == 8) {
266  for (int i=0; i<readBytes; i++) {
267  (*m_data)[index_green8_to_rgb8(m_frameRead)] = m_readData[i];
268  m_frameRead++;
269  }
270  return;
271  }
272  else if (m_params.depth == 16) {
273  for (int i=0; i<readBytes; i++) {
274  (*m_data)[index_green16_to_rgb16(m_frameRead)] = m_readData[i];
275  m_frameRead++;
276  }
277  return;
278  }
279  break;
280 
281  case SANE_FRAME_BLUE:
282  if (m_params.depth == 8) {
283  for (int i=0; i<readBytes; i++) {
284  (*m_data)[index_blue8_to_rgb8(m_frameRead)] = m_readData[i];
285  m_frameRead++;
286  }
287  return;
288  }
289  else if (m_params.depth == 16) {
290  for (int i=0; i<readBytes; i++) {
291  (*m_data)[index_blue16_to_rgb16(m_frameRead)] = m_readData[i];
292  m_frameRead++;
293  }
294  return;
295  }
296  break;
297  }
298 
299  kDebug() << "Format" << m_params.format
300  << "and depth" << m_params.format
301  << "is not yet suppoeted by libksane!";
302  m_readStatus = READ_ERROR;
303  return;
304  }
305 
306  bool KSaneScanThread::saneStartDone()
307  {
308  return m_saneStartDone;
309  }
310 
311 } // NameSpace KSaneIface
QByteArray::clear
void clear()
KSaneIface::KSaneScanThread::setImageInverted
void setImageInverted(bool)
Definition: ksane_scan_thread.cpp:51
index_red16_to_rgb16
#define index_red16_to_rgb16(i)
Definition: ksane_scan_thread.cpp:204
QByteArray::reserve
void reserve(int size)
QByteArray
index_red8_to_rgb8
#define index_red8_to_rgb8(i)
Definition: ksane_scan_thread.cpp:203
KSaneIface::KSaneScanThread::READ_ERROR
Definition: ksane_scan_thread.h:52
index_blue16_to_rgb16
#define index_blue16_to_rgb16(i)
Definition: ksane_scan_thread.cpp:210
KSaneIface::KSaneScanThread::ReadStatus
ReadStatus
Definition: ksane_scan_thread.h:49
KSaneIface::KSaneScanThread::READ_ON_GOING
Definition: ksane_scan_thread.h:51
KSaneIface::KSaneScanThread::READ_READY
Definition: ksane_scan_thread.h:54
KSaneIface::KSaneScanThread::scanProgress
int scanProgress()
Definition: ksane_scan_thread.cpp:71
SCAN_READ_CHUNK_SIZE
#define SCAN_READ_CHUNK_SIZE
Definition: ksane_scan_thread.h:41
KSaneIface::KSaneScanThread::READ_CANCEL
Definition: ksane_scan_thread.h:53
index_blue8_to_rgb8
#define index_blue8_to_rgb8(i)
Definition: ksane_scan_thread.cpp:209
QByteArray::append
QByteArray & append(char ch)
KSaneIface::KSaneScanThread::saneStartDone
bool saneStartDone()
Definition: ksane_scan_thread.cpp:306
KSaneIface::KSaneScanThread::frameStatus
ReadStatus frameStatus()
Definition: ksane_scan_thread.cpp:61
KSaneIface::KSaneScanThread::saneStatus
SANE_Status saneStatus()
Definition: ksane_scan_thread.cpp:56
KSaneIface::KSaneScanThread::saneParameters
SANE_Parameters saneParameters()
Definition: ksane_scan_thread.cpp:86
KSaneIface::KSaneScanThread::cancelScan
void cancelScan()
Definition: ksane_scan_thread.cpp:66
index_green8_to_rgb8
#define index_green8_to_rgb8(i)
Definition: ksane_scan_thread.cpp:206
QThread
KSaneIface::KSaneScanThread::KSaneScanThread
KSaneScanThread(SANE_Handle handle, QByteArray *data)
Definition: ksane_scan_thread.cpp:37
index_green16_to_rgb16
#define index_green16_to_rgb16(i)
Definition: ksane_scan_thread.cpp:207
KSaneIface::KSaneScanThread::run
void run()
Definition: ksane_scan_thread.cpp:91
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:19:47 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libs/libksane/libksane

Skip menu "libs/libksane/libksane"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdegraphics API Reference

Skip menu "kdegraphics API Reference"
  •     libkdcraw
  •     libkexiv2
  •     libkipi
  •     libksane
  • okular

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal