333 lines
9.8 KiB
C++
333 lines
9.8 KiB
C++
|
|
|
|
#include <texception.h>
|
|
#include <tscanner.h>
|
|
#include "tscannertwain.h"
|
|
#include "tscannerutil.h"
|
|
|
|
using namespace TScannerUtil;
|
|
|
|
extern "C" {
|
|
#include "../common/twain/ttwain_util.h"
|
|
}
|
|
|
|
/* callback used to handle TTWAIN done/error status*/
|
|
|
|
void throwIT(const char *msg) { throw TException(msg); }
|
|
|
|
extern "C" void TTWAIN_ErrorBox(const char *msg) { throwIT(msg); }
|
|
|
|
extern "C" int onDoneCB(UCHAR *buffer, TTWAIN_PIXTYPE pixelType, int lx, int ly,
|
|
int wrap, float xdpi, float ydpi, void *usrData) {
|
|
TRasterP ras;
|
|
switch (pixelType) {
|
|
case TTWAIN_BW:
|
|
case TTWAIN_WB: {
|
|
try {
|
|
TRasterGR8P ras8(lx, ly);
|
|
copy90BWBufferToRasGR8(buffer, lx, ly, wrap, (pixelType == TTWAIN_BW),
|
|
ras8, 1, 0);
|
|
ras8->xMirror();
|
|
ras8->yMirror();
|
|
ras = ras8;
|
|
} catch (...) {
|
|
}
|
|
} break;
|
|
|
|
case TTWAIN_RGB24: {
|
|
try {
|
|
TRaster32P ras32(lx, ly);
|
|
copyRGBBufferToTRaster32(buffer, lx, ly, ras32, false);
|
|
ras = ras32;
|
|
} catch (...) {
|
|
}
|
|
} break;
|
|
|
|
case TTWAIN_GRAY8: {
|
|
try {
|
|
TRasterGR8P ras8(lx, ly);
|
|
copyGR8BufferToTRasterGR8(buffer, lx, ly, ras8, false);
|
|
ras = ras8;
|
|
} catch (...) {
|
|
}
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
TRasterImageP rasImg;
|
|
if (ras) {
|
|
rasImg = TRasterImageP(ras);
|
|
rasImg->setDpi(xdpi, ydpi);
|
|
// rasImg->sethPos(hpos);
|
|
rasImg->setSavebox(ras->getBounds());
|
|
}
|
|
|
|
TScanner *scannerDevice = reinterpret_cast<TScanner *>(usrData);
|
|
scannerDevice->notifyImageDone(rasImg);
|
|
TTWAIN_FreeMemory(buffer);
|
|
scannerDevice->decrementPaperLeftCount();
|
|
return scannerDevice->getPaperLeftCount();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
extern "C" void onErrorCB(void *usrData, void *alwaysZero) {
|
|
TScanner *scannerDevice = reinterpret_cast<TScanner *>(usrData);
|
|
scannerDevice->notifyError();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TScannerTwain::TScannerTwain() {}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TScannerTwain::~TScannerTwain() {}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace {
|
|
bool deviceSelected = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void TScannerTwain::selectDevice() {
|
|
TTWAIN_SelectImageSource(0);
|
|
deviceSelected = true;
|
|
|
|
if (TTWAIN_OpenDefaultSource()) {
|
|
QString twainVersion(TTWAIN_GetTwainVersion());
|
|
QString manufacturer(TTWAIN_GetManufacturer());
|
|
QString productFamily(TTWAIN_GetProductFamily());
|
|
QString productName(TTWAIN_GetProductName());
|
|
QString version(TTWAIN_GetVersion());
|
|
|
|
TTWAIN_CloseAll(0);
|
|
|
|
if (manufacturer != "") {
|
|
// se c'e' il nome della marca lo tolgo dal productFamily e productName
|
|
productFamily.replace(manufacturer, "");
|
|
productName.replace(manufacturer, "");
|
|
}
|
|
setName(manufacturer + " " + productFamily + " " + productName + " (" +
|
|
version + ")");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool TScannerTwain::isDeviceSelected() { return deviceSelected; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool TScannerTwain::isDeviceAvailable() { return !!TTWAIN_IsAvailable(); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// TODO!! renderla un update
|
|
void TScannerTwain::updateParameters(TScannerParameters ¶m) {
|
|
int rc = TTWAIN_OpenDefaultSource();
|
|
if (!rc) return;
|
|
|
|
#ifdef MACOSX
|
|
// TTWAIN_DumpCapabilities(printf);
|
|
#endif
|
|
if (isAreaSupported()) {
|
|
float w, h;
|
|
TTWAIN_GetPhysicalWidthWoAdf(&w);
|
|
TTWAIN_GetPhysicalHeightWoAdf(&h);
|
|
double width_mm = w * 25.4;
|
|
double height_mm = h * 25.4;
|
|
|
|
param.setMaxPaperSize(width_mm, height_mm);
|
|
// sembra sbagliato: bisognerebbe comunque tenere conto del paperFormat
|
|
// selezionato
|
|
// param.m_scanArea = TRectD(0,0, width_mm,height_mm);
|
|
}
|
|
TScanParam defaultTwainParam(0., 255., 128., 1.);
|
|
if (TTWAIN_IsCapBrightnessSupported()) {
|
|
m_brightness.m_supported = true;
|
|
TTWAIN_GetBrightness(&m_brightness.m_min, &m_brightness.m_max,
|
|
&m_brightness.m_step, &m_brightness.m_def);
|
|
} else {
|
|
// m_brightness.m_def = m_brightness.m_max = m_brightness.m_min =
|
|
// m_brightness.m_step = 0.;
|
|
m_brightness.update(defaultTwainParam);
|
|
m_brightness.m_supported = false;
|
|
}
|
|
// m_brightness.m_value = m_brightness.m_def;
|
|
param.m_brightness.update(m_brightness);
|
|
|
|
if (TTWAIN_IsCapContrastSupported()) {
|
|
m_contrast.m_supported = true;
|
|
TTWAIN_GetContrast(&m_contrast.m_min, &m_contrast.m_max, &m_contrast.m_step,
|
|
&m_contrast.m_def);
|
|
} else {
|
|
// m_contrast.m_def = m_contrast.m_max = m_contrast.m_min =
|
|
// m_contrast.m_step = 0.;
|
|
m_contrast.update(defaultTwainParam);
|
|
m_contrast.m_supported = false;
|
|
}
|
|
// m_contrast.m_value = m_contrast.m_def;
|
|
param.m_contrast.update(m_contrast);
|
|
|
|
if (TTWAIN_IsCapThresholdSupported()) {
|
|
m_threshold.m_supported = true;
|
|
TTWAIN_GetThreshold(&m_threshold.m_min, &m_threshold.m_max,
|
|
&m_threshold.m_step, &m_threshold.m_def);
|
|
} else {
|
|
// m_threshold.m_def = m_threshold.m_max = m_threshold.m_min =
|
|
// m_threshold.m_step = 0.;
|
|
m_threshold.update(defaultTwainParam);
|
|
m_threshold.m_supported = false;
|
|
}
|
|
|
|
// m_threshold.m_value = m_threshold.m_def;
|
|
param.m_threshold.update(m_threshold);
|
|
|
|
if (TTWAIN_IsCapResolutionSupported()) {
|
|
m_dpi.m_supported = true;
|
|
TTWAIN_GetResolution(&m_dpi.m_min, &m_dpi.m_max, &m_dpi.m_step,
|
|
&m_dpi.m_def);
|
|
param.m_dpi.update(m_dpi);
|
|
} else {
|
|
// m_dpi.m_def = m_dpi.m_max = m_dpi.m_min = m_dpi.m_step = 0.;
|
|
param.m_dpi.m_supported = false;
|
|
}
|
|
// m_dpi.m_value = m_dpi.m_def;
|
|
|
|
/*
|
|
param.m_twainVersion = string(TTWAIN_GetTwainVersion());
|
|
param.m_manufacturer = string(TTWAIN_GetManufacturer ());
|
|
param.m_prodFamily = string(TTWAIN_GetProductFamily());
|
|
param.m_productName = string(TTWAIN_GetProductName ());
|
|
param.m_version = string(TTWAIN_GetVersion());
|
|
*/
|
|
|
|
bool bw = !!TTWAIN_SupportsPixelType(TTWAIN_BW) ||
|
|
!!TTWAIN_SupportsPixelType(TTWAIN_WB);
|
|
bool gray = !!TTWAIN_SupportsPixelType(TTWAIN_GRAY8);
|
|
bool rgb = !!TTWAIN_SupportsPixelType(TTWAIN_RGB24);
|
|
|
|
param.setSupportedTypes(bw, gray, rgb);
|
|
|
|
TTWAIN_CloseAll(0);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void setupParameters(const TScannerParameters ¶ms, bool isAreaSupported) {
|
|
if (isAreaSupported) {
|
|
TRectD scanArea = params.getScanArea();
|
|
float L = (float)(scanArea.getP00().x / 25.4);
|
|
float T = (float)(scanArea.getP00().y / 25.4);
|
|
float R = (float)(scanArea.getP11().x / 25.4);
|
|
float B = (float)(scanArea.getP11().y / 25.4);
|
|
TTWAIN_SetImageLayout(L, T, R, B);
|
|
}
|
|
|
|
TTWAIN_PIXTYPE pt;
|
|
switch (params.getScanType()) {
|
|
case TScannerParameters::BW:
|
|
pt = TTWAIN_BW;
|
|
break;
|
|
case TScannerParameters::GR8:
|
|
pt = TTWAIN_GRAY8;
|
|
break;
|
|
case TScannerParameters::RGB24:
|
|
pt = TTWAIN_RGB24;
|
|
break;
|
|
default:
|
|
/* assert(0);*/
|
|
pt = TTWAIN_RGB24;
|
|
break;
|
|
}
|
|
|
|
TTWAIN_SetPixelType(pt);
|
|
if (params.m_dpi.m_supported) TTWAIN_SetResolution(params.m_dpi.m_value);
|
|
|
|
if (params.m_brightness.m_supported)
|
|
TTWAIN_SetBrightness(params.m_brightness.m_value);
|
|
|
|
if (params.m_contrast.m_supported)
|
|
TTWAIN_SetContrast(params.m_contrast.m_value);
|
|
|
|
if (params.m_threshold.m_supported)
|
|
TTWAIN_SetThreshold(params.m_threshold.m_value);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void openAndSetupTwain() {
|
|
int rc = TTWAIN_OpenDefaultSource();
|
|
if (rc) {
|
|
TTWAIN_SetTwainUsage(TTWAIN_MODE_UNLEASHED);
|
|
if (TTWAIN_IsCapDeviceOnLineSupported()) {
|
|
int status = TTWAIN_IsDeviceOnLine();
|
|
if (status == 0) {
|
|
}
|
|
}
|
|
}
|
|
TTWAIN_SetUIStatus(TRUE);
|
|
}
|
|
|
|
void TScannerTwain::acquire(const TScannerParameters ¶ms, int paperCount) {
|
|
openAndSetupTwain();
|
|
|
|
// int feeder = TTWAIN_IsFeederLoaded();
|
|
int feeder = params.isPaperFeederEnabled();
|
|
m_paperLeft = paperCount;
|
|
int rc;
|
|
|
|
#ifdef MACOSX
|
|
// pezza solo HP su MACOSX per gestire la scansione di piu' frame
|
|
bool ishp = !!(strcasestr(TTWAIN_GetProductName(), "hp"));
|
|
#else
|
|
bool ishp = false;
|
|
#endif
|
|
if (ishp) {
|
|
for (int i = 0; i < paperCount; ++i) {
|
|
printf("scanning %d/%d\n", i + 1, paperCount);
|
|
if (i == 0) {
|
|
setupParameters(params, isAreaSupported());
|
|
TTWAIN_SetOnDoneCallback(onDoneCB, this);
|
|
TTWAIN_SetOnErrorCallback(onErrorCB, this);
|
|
} else
|
|
openAndSetupTwain();
|
|
|
|
rc = TTWAIN_SetXferMech(TTWAIN_TRANSFERMODE_MEMORY, 0, 0, 0, 0, 1);
|
|
int acq_rc = TTWAIN_AcquireMemory(0);
|
|
|
|
if (acq_rc == 0) break; // error, or the user has closed the TWAIN UI
|
|
if (!feeder && ((paperCount - i) > 1)) notifyNextPaper();
|
|
TTWAIN_CloseAll(0);
|
|
}
|
|
} else {
|
|
for (int i = 0; i < (feeder ? 1 : paperCount); ++i) {
|
|
printf("scanning %d/%d\n", i + 1, paperCount);
|
|
setupParameters(params, isAreaSupported());
|
|
|
|
rc = TTWAIN_SetXferMech(TTWAIN_TRANSFERMODE_MEMORY, 0, 0, 0, 0,
|
|
paperCount);
|
|
|
|
TTWAIN_SetOnDoneCallback(onDoneCB, this);
|
|
TTWAIN_SetOnErrorCallback(onErrorCB, this);
|
|
int acq_rc = TTWAIN_AcquireMemory(0);
|
|
|
|
if (acq_rc == 0) break; // error, or the user has closed the TWAIN UI
|
|
if (!feeder && ((paperCount - i) > 1)) notifyNextPaper();
|
|
}
|
|
TTWAIN_CloseAll(0);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool TScannerTwain::isAreaSupported() {
|
|
/*
|
|
TTWAIN_IsCapPhysicalWidthSupported (void);
|
|
TTWAIN_IsCapPhysicalHeightSupported (void);
|
|
*/
|
|
return !!TTWAIN_IsCapImageLayoutSupported();
|
|
}
|