#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();
}