#include "tscanner.h" #include "tscannertwain.h" #include "texception.h" #include "tscannerepson.h" #include "tstream.h" #include "tconvert.h" #include "tfilepath.h" #include "tfilepath_io.h" #include "tenv.h" #include "tsystem.h" extern "C" { #include "../common/twain/ttwain_util.h" } //=================================================================== // // TScanParam // //------------------------------------------------------------------- void TScanParam::update(const TScanParam &model) { m_supported = model.m_supported; m_min = model.m_min; m_max = model.m_max; m_def = model.m_def; m_step = model.m_step; m_value = tcrop(m_value, m_min, m_max); } //=================================================================== // // TScannerParameters // //------------------------------------------------------------------- const std::string BlackAndWhite = "Black & White"; const std::string Graytones = "Graytones"; const std::string Rgbcolors = "RGB Color"; //------------------------------------------------------------------- TScannerParameters::TScannerParameters() : m_bw(false), m_gray(false), m_rgb(false), m_scanType(None), m_scanArea(TRectD()), m_cropBox(TRectD()), m_isPreview(false), m_maxPaperSize(TDimensionD(0, 0)), m_paperOverflow(false), m_brightness(), m_contrast(), m_threshold(), m_dpi(), m_paperFeeder(), m_twainVersion(), m_manufacturer(), m_prodFamily(), m_productName(), m_version(), m_reverseOrder(false), m_validatedByCurrentScanner(false) { m_threshold.m_value = 127; m_brightness.m_value = 127; } //------------------------------------------------------------------------------------------------- TScannerParameters::~TScannerParameters() { } //------------------------------------------------------------------------------------------------- void TScannerParameters::assign(const TScannerParameters *src) { *this = *src; } //------------------------------------------------------------------------------------------------- void TScannerParameters::setSupportedTypes(bool bw, bool gray, bool rgb) { m_bw = bw; m_gray = gray; m_rgb = rgb; if (!m_bw && !m_gray && !m_rgb) { m_scanType = None; } else { switch (m_scanType) { case BW: if (!m_bw) m_scanType = m_gray ? GR8 : RGB24; break; case GR8: if (!m_gray) m_scanType = m_rgb ? RGB24 : BW; break; case RGB24: if (!m_rgb) m_scanType = m_gray ? GR8 : BW; break; case None: if (gray) m_scanType = GR8; else { if (rgb) m_scanType = RGB24; else if (bw) m_scanType = BW; } break; } } } //------------------------------------------------------------------------------------------------- bool TScannerParameters::isSupported(ScanType scanType) const { switch (scanType) { case BW: return m_bw; case GR8: return m_gray; case RGB24: return m_rgb; default: assert(0); return false; } } //------------------------------------------------------------------------------------------------- void TScannerParameters::cropScanArea() { m_paperOverflow = false; if (m_maxPaperSize.lx == 0 || m_maxPaperSize.ly == 0) { // probabilmente non e' ancora stato selezionato uno scanner e quindi non e' // definita una maxPaperSize return; } assert(m_maxPaperSize.lx > 0 && m_maxPaperSize.ly > 0); if (m_scanArea.x1 > m_maxPaperSize.lx) { m_paperOverflow = true; m_scanArea.x1 = m_maxPaperSize.lx; } if (m_scanArea.y1 > m_maxPaperSize.ly) { m_paperOverflow = true; m_scanArea.y1 = m_maxPaperSize.ly; } } //------------------------------------------------------------------------------------------------- void TScannerParameters::setMaxPaperSize(double maxWidth, double maxHeight) { // assert(maxWidth>0 && maxHeight>0); m_maxPaperSize = TDimensionD(maxWidth, maxHeight); cropScanArea(); } //----------------------------------------------------------------------------- void TScannerParameters::setPaperFormat(std::string paperFormat) { TPaperFormatManager *formatManager = TPaperFormatManager::instance(); assert(formatManager->isValidFormat(paperFormat)); if (!formatManager->isValidFormat(paperFormat)) paperFormat = formatManager->getDefaultFormat(); m_paperFormat = paperFormat; TDimensionD d = TPaperFormatManager::instance()->getSize(paperFormat); m_scanArea = TRectD(TPointD(0, 0), d); cropScanArea(); if (m_cropBox == TRectD()) m_cropBox = m_scanArea; } //----------------------------------------------------------------------------- void TScannerParameters::updatePaperFormat() { if (m_paperFormat == "") m_paperFormat = TPaperFormatManager::instance()->getDefaultFormat(); setPaperFormat(m_paperFormat); } //----------------------------------------------------------------------------- void TScannerParameters::setScanType(ScanType scanType) { assert(scanType == None || scanType == BW || scanType == GR8 || scanType == RGB24); m_scanType = scanType; } //----------------------------------------------------------------------------- void TScannerParameters::adaptToCurrentScanner() { try { if (TScanner::instance()->isDeviceSelected()) { TScanner::instance()->updateParameters(*this); m_validatedByCurrentScanner = true; } } catch (TException &) { //TMessage::error("%1", e.getMessage()); } } //------------------------------------------------------------------------------------------------- void TScannerParameters::saveData(TOStream &os) const { std::map attr; attr["fmt"] = m_paperFormat; os.openCloseChild("paper", attr); if (m_paperFeeder.m_value == 1.0) { attr.clear(); os.openCloseChild("autoFeeder", attr); } if (m_reverseOrder) { attr.clear(); os.openCloseChild("reverseOrder", attr); } if (m_scanType != None) { std::string scanTypeString = Rgbcolors; switch (m_scanType) { case BW: scanTypeString = BlackAndWhite; break; case GR8: scanTypeString = Graytones; break; case RGB24: scanTypeString = Rgbcolors; break; } attr.clear(); attr["value"] = scanTypeString; os.openCloseChild("mode", attr); } if (m_dpi.m_supported) { attr.clear(); attr["value"] = std::to_string(m_dpi.m_value); os.openCloseChild("dpi", attr); } if (m_brightness.m_supported) { attr.clear(); attr["value"] = std::to_string(m_brightness.m_value); os.openCloseChild("brightness", attr); } if (m_contrast.m_supported) { attr.clear(); attr["value"] = std::to_string(m_contrast.m_value); os.openCloseChild("contrast", attr); } if (m_threshold.m_supported) { attr.clear(); attr["value"] = std::to_string(m_threshold.m_value); os.openCloseChild("threshold", attr); } } //------------------------------------------------------------------------------------------------- void TScannerParameters::loadData(TIStream &is) { std::string tagName; while (is.matchTag(tagName)) { if (tagName == "dpi") { std::string s = is.getTagAttribute("value"); if (isDouble(s)) m_dpi.m_value = std::stof(s); } else if (tagName == "brightness") { std::string s = is.getTagAttribute("value"); if (isDouble(s)) m_brightness.m_value = std::stof(s); } else if (tagName == "threshold") { std::string s = is.getTagAttribute("value"); if (isDouble(s)) m_threshold.m_value = std::stof(s); } else if (tagName == "contrast") { std::string s = is.getTagAttribute("value"); if (isDouble(s)) m_contrast.m_value = std::stof(s); } else if (tagName == "autoFeeder") { m_paperFeeder.m_value = 1.0; } else if (tagName == "reverseOrder") { m_reverseOrder = true; } else if (tagName == "mode") { std::string scanTypeString = is.getTagAttribute("value"); m_scanType = None; if (scanTypeString == BlackAndWhite) m_scanType = BW; else if (scanTypeString == Graytones) m_scanType = GR8; else if (scanTypeString == Rgbcolors) m_scanType = RGB24; } else if (tagName == "paper") { std::string paperFormat = is.getTagAttribute("fmt"); if (paperFormat != "") setPaperFormat(paperFormat); } } m_validatedByCurrentScanner = false; } //=================================================================== // // TScanner // //------------------------------------------------------------------- namespace { TScanner *instanceTwain = 0; TScanner *instanceEpson = 0; } //------------------------------------------------------------------- bool TScanner::m_isTwain = true; //------------------------------------------------------------------- namespace { class Cleaner { public: bool m_activated; Cleaner() : m_activated(false) {} ~Cleaner() { TScanner *scannerToDestroy = 0; if (m_activated) scannerToDestroy = TScanner::instance(); delete scannerToDestroy; } }; Cleaner MyCleaner; }; //------------------------------------------------------------------- // #define DUMMYSCAN #ifdef DUMMYSCAN class TScannerDummy : public TScanner { public: TScannerDummy() {} ~TScannerDummy() {} void selectDevice() {} bool isDeviceAvailable() { return true; } void updateParameters(TScannerParameters ¶meters) { parameters.setSupportedTypes(false, true, true); parameters.setMaxPaperSize(1000., 1000.); parameters.enablePaperFeeder(true); parameters.m_brightness.update(TScanParam(0, 255, 128, 1)); parameters.m_contrast.update(TScanParam(0, 255, 128, 1)); parameters.m_threshold.update(TScanParam(0, 255, 128, 1)); parameters.m_dpi.update(TScanParam(60, 1200, 100, 1)); setName("DummyScanner"); } bool isTwain() const { return true; } void acquire(const TScannerParameters ¶m, int paperCount) { return; } bool isAreaSupported() { return true; } }; #endif //----------------------------------------------------------------------------- TScanner *TScanner::instance() { MyCleaner.m_activated = true; #ifdef DUMMYSCAN static TScannerDummy dummy = TScannerDummy(); return &dummy; #else if (m_isTwain) { if (instanceEpson) { TScannerEpson *se = (TScannerEpson *)instanceEpson; se->closeIO(); //delete m_instanceEpson; //e' singletone, perche' buttarlo? (vinz) //m_instanceEpson=0; } if (!instanceTwain) instanceTwain = new TScannerTwain(); } else if (!m_isTwain) { if (instanceTwain) { //delete m_instanceTwain; //e' singletone, perche' buttarlo? (vinz) //m_instanceTwain=0; TTWAIN_CloseAll(0); } if (!instanceEpson) instanceEpson = new TScannerEpson(); } return (m_isTwain) ? instanceTwain : instanceEpson; #endif } //----------------------------------------------------------------------------- TScanner::TScanner() : m_paperLeft(0) { } //----------------------------------------------------------------------------- TScanner::~TScanner() { if (instanceEpson) { TScannerEpson *se = (TScannerEpson *)instanceEpson; se->closeIO(); } } //----------------------------------------------------------------------------- void TScanner::addListener(TScannerListener *lst) { m_listeners.insert(lst); } //----------------------------------------------------------------------------- void TScanner::removeListener(TScannerListener *lst) { m_listeners.erase(lst); } //----------------------------------------------------------------------------- void TScanner::notifyImageDone(const TRasterImageP &img) { std::set::iterator it = m_listeners.begin(); for (; it != m_listeners.end(); ++it) { (*it)->onImage(img); } } //----------------------------------------------------------------------------- void TScanner::notifyNextPaper() { std::set::iterator it = m_listeners.begin(); for (; it != m_listeners.end(); ++it) { (*it)->onNextPaper(); } } //----------------------------------------------------------------------------- void TScanner::notifyAutomaticallyNextPaper() { std::set::iterator it = m_listeners.begin(); for (; it != m_listeners.end(); ++it) { (*it)->onAutomaticallyNextPaper(); } } //----------------------------------------------------------------------------- void TScanner::notifyError() { std::set::iterator it = m_listeners.begin(); for (; it != m_listeners.end(); ++it) { (*it)->onError(); } } //----------------------------------------------------------------------------- /*! If one listener is set to cancel return true. */ bool TScanner::isScanningCanceled() { std::set::iterator it = m_listeners.begin(); for (; it != m_listeners.end(); ++it) { if ((*it)->isCanceled()) return true; } return false; } //=================================================================== // // TPaperFormatManager // //------------------------------------------------------------------- namespace { const std::pair defaultPaperFormat("A4 paper", TDimensionD(210.00, 297.00)); } //----------------------------------------------------------------------------- TPaperFormatManager::TPaperFormatManager() { readPaperFormats(); // se non c'e' aggiungo il formato di default. In questo modo e' sempre definito if (!isValidFormat(defaultPaperFormat.first)) m_formats[defaultPaperFormat.first] = Format(defaultPaperFormat.second); } //----------------------------------------------------------------------------- TPaperFormatManager *TPaperFormatManager::instance() { static TPaperFormatManager _instance; return &_instance; } //----------------------------------------------------------------------------- void TPaperFormatManager::getFormats(std::vector &names) const { for (FormatTable::const_iterator it = m_formats.begin(); it != m_formats.end(); ++it) names.push_back(it->first); } //----------------------------------------------------------------------------- TDimensionD TPaperFormatManager::getSize(std::string name) const { FormatTable::const_iterator it = m_formats.find(name); if (it == m_formats.end()) return TDimensionD(0., 0.); else return it->second.m_size; } //----------------------------------------------------------------------------- bool TPaperFormatManager::isValidFormat(std::string name) const { FormatTable::const_iterator it = m_formats.find(name); return it != m_formats.end(); } //----------------------------------------------------------------------------- std::string TPaperFormatManager::getDefaultFormat() const { return defaultPaperFormat.first; } //----------------------------------------------------------------------------- void TPaperFormatManager::readPaperFormat(const TFilePath &path) { if (path.getType() != "pap") return; Tifstream is(path); std::string name; TDimensionD size(0, 0); while (is) { char buffer[1024]; is.getline(buffer, sizeof buffer); // i e' il carattere successivo alla fine della linea unsigned int i = 0; for (i = 0; i < sizeof buffer && buffer[i]; i++) { } if (i > 0 && buffer[i - 1] == '\n') i--; while (i > 0 && buffer[i - 1] == ' ') i--; unsigned int j = 0; unsigned int k = 0; // j e' il carattere successivo alla fine del primo token for (j = 0; j < i && buffer[j] != ' '; j++) { } // k e' l'inizio del secondo token (se c'e', altrimenti == i) for (k = j; k < i && buffer[k] == ' '; k++) { } std::string value; if (k < i) value = std::string(buffer + k, i - k); if (buffer[0] == '#') { if (k < i && name == "") name = value; } else if (std::string(buffer).find("WIDTH") == 0) { if (isDouble(value)) size.lx = std::stod(value); } else if (std::string(buffer).find("LENGTH") == 0) { if (isDouble(value)) size.ly = std::stod(value); } } if (name == "" || size.lx == 0 || size.ly == 0) { // TMessage::error("Error reading paper format file : %1",path); } else m_formats[name] = Format(size); } //----------------------------------------------------------------------------- void TPaperFormatManager::readPaperFormats() { TFilePathSet fps; TFilePath papDir = TEnv::getConfigDir() + "pap"; if (!TFileStatus(papDir).isDirectory()) { // TMessage::error("E_CanNotReadDirectory_%1", papDir); return; } try { fps = TSystem::readDirectory(papDir); } catch (TException &) { // TMessage::error("E_CanNotReadDirectory_%1", papDir); return; } TFilePathSet::const_iterator it = fps.begin(); for (; it != fps.end(); ++it) readPaperFormat(*it); }