summaryrefslogtreecommitdiffstats
path: root/libkscan/previewer.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /libkscan/previewer.cpp
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libkscan/previewer.cpp')
-rw-r--r--libkscan/previewer.cpp871
1 files changed, 871 insertions, 0 deletions
diff --git a/libkscan/previewer.cpp b/libkscan/previewer.cpp
new file mode 100644
index 00000000..f4133ee9
--- /dev/null
+++ b/libkscan/previewer.cpp
@@ -0,0 +1,871 @@
+
+/* This file is part of the KDE Project
+ Copyright (C) 2000 Klaas Freitag <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qfontmetrics.h>
+#include <qhbox.h>
+#include <qtooltip.h>
+#include <qpopupmenu.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qcombobox.h>
+#include <qradiobutton.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcombobox.h>
+#include <kaction.h>
+#include <kstandarddirs.h>
+
+#include "previewer.h"
+#include "img_canvas.h"
+#include "sizeindicator.h"
+#include "devselector.h" /* for definition of config key :( */
+#include "kscandevice.h"
+#include <qslider.h>
+#include <qcheckbox.h>
+#include <kconfig.h>
+#include <qbuttongroup.h>
+#include <qvbuttongroup.h>
+#include <kmessagebox.h>
+#include <qvaluevector.h>
+
+#define ID_CUSTOM 0
+#define ID_A4 1
+#define ID_A5 2
+#define ID_A6 3
+#define ID_9_13 4
+#define ID_10_15 5
+#define ID_LETTER 6
+
+/** Config tags for autoselection **/
+#define CFG_AUTOSEL_DO "doAutoselection" /* do it or not */
+#define CFG_AUTOSEL_THRESH "autoselThreshold" /* threshold */
+#define CFG_AUTOSEL_DUSTSIZE "autoselDustsize" /* dust size */
+/* tag if a scan of the empty scanner results in black or white image */
+#define CFG_SCANNER_EMPTY_BG "scannerBackgroundWhite"
+
+/* Defaultvalues for the threshold for the autodetection */
+#define DEF_THRESH_BLACK "45"
+#define DEF_THRESH_WHITE "240"
+
+/* Items for the combobox to set the color of an empty scan */
+#define BG_ITEM_BLACK 0
+#define BG_ITEM_WHITE 1
+
+
+class Previewer::PreviewerPrivate
+{
+public:
+ PreviewerPrivate():
+ m_doAutoSelection(false),
+ m_autoSelThresh(0),
+ m_dustsize(5),
+ m_bgIsWhite(false),
+ m_sliderThresh(0),
+ m_sliderDust(0),
+ m_cbAutoSel(0),
+ m_cbBackground(0),
+ m_autoSelGroup(0),
+ m_scanner(0)
+ {
+ }
+ bool m_doAutoSelection; /* switch auto-selection on and off */
+ int m_autoSelThresh; /* threshold for auto selection */
+ int m_dustsize; /* dustsize for auto selection */
+
+ bool m_bgIsWhite; /* indicates if a scan without paper
+ * results in black or white */
+ QSlider *m_sliderThresh;
+ QSlider *m_sliderDust;
+ QCheckBox *m_cbAutoSel;
+ QComboBox *m_cbBackground;
+ QGroupBox *m_autoSelGroup;
+ KScanDevice *m_scanner;
+
+ QMemArray<long> m_heightSum;
+ QMemArray<long> m_widthSum;
+};
+
+Previewer::Previewer(QWidget *parent, const char *name )
+ : QWidget(parent,name)
+{
+ d = new PreviewerPrivate();
+
+ // beautification to look like the left scanparams widget in the dialog
+ QHBoxLayout *htop = new QHBoxLayout( this );
+ QFrame *frame = new QFrame( this );
+ frame->setFrameStyle( QFrame::Panel | QFrame::Raised );
+ frame->setLineWidth( 1 );
+ htop->addWidget( frame );
+
+ QVBoxLayout *top = new QVBoxLayout( frame, KDialog::marginHint(), KDialog::spacingHint() );
+ layout = new QHBoxLayout( KDialog::spacingHint() );
+ top->addLayout( layout, 9 );
+ QVBoxLayout *left = new QVBoxLayout( KDialog::spacingHint() );
+ layout->addLayout( left, 2 );
+
+ /* Load autoselection values from Config file */
+ KConfig *cfg = KGlobal::config();
+ cfg->setGroup( GROUP_STARTUP );
+
+ /* Units etc. TODO: get from Config */
+ sizeUnit = KRuler::Millimetres;
+ displayUnit = sizeUnit;
+ d->m_autoSelThresh = 240;
+
+ overallHeight = 295; /* Default DIN A4 */
+ overallWidth = 210;
+ kdDebug(29000) << "Previewer: got Overallsize: " <<
+ overallWidth << " x " << overallHeight << endl;
+ img_canvas = new ImageCanvas( frame );
+
+ img_canvas->setDefaultScaleKind( ImageCanvas::DYNAMIC );
+ img_canvas->enableContextMenu(true);
+ img_canvas->repaint();
+ layout->addWidget( img_canvas, 6 );
+
+ /* Actions for the previewer zoom */
+ KAction *act;
+ act = new KAction(i18n("Scale to W&idth"), "scaletowidth", CTRL+Key_I,
+ this, SLOT( slScaleToWidth()), this, "preview_scaletowidth" );
+ act->plug( img_canvas->contextMenu());
+
+ act = new KAction(i18n("Scale to &Height"), "scaletoheight", CTRL+Key_H,
+ this, SLOT( slScaleToHeight()), this, "preview_scaletoheight" );
+ act->plug( img_canvas->contextMenu());
+
+ /*Signals: Control the custom-field and show size of selection */
+ connect( img_canvas, SIGNAL(newRect()), this, SLOT(slCustomChange()));
+ connect( img_canvas, SIGNAL(newRect(QRect)), this, SLOT(slNewDimen(QRect)));
+
+ /* Stuff for the preview-Notification */
+ left->addWidget( new QLabel( i18n("<B>Preview</B>"), frame ), 1);
+
+ // Create a button group to contain buttons for Portrait/Landscape
+ bgroup = new QVButtonGroup( i18n("Scan Size"), frame );
+
+ // -----
+ pre_format_combo = new QComboBox( frame, "PREVIEWFORMATCOMBO" );
+ pre_format_combo->insertItem( i18n( "Custom" ), ID_CUSTOM);
+ pre_format_combo->insertItem( i18n( "DIN A4" ), ID_A4);
+ pre_format_combo->insertItem( i18n( "DIN A5" ), ID_A5);
+ pre_format_combo->insertItem( i18n( "DIN A6" ), ID_A6);
+ pre_format_combo->insertItem( i18n( "9x13 cm" ), ID_9_13 );
+ pre_format_combo->insertItem( i18n( "10x15 cm" ), ID_10_15 );
+ pre_format_combo->insertItem( i18n( "Letter" ), ID_LETTER);
+
+ connect( pre_format_combo, SIGNAL(activated (int)),
+ this, SLOT( slFormatChange(int)));
+
+ left->addWidget( pre_format_combo, 1 );
+
+ /** Potrait- and Landscape Selector **/
+ QFontMetrics fm = bgroup->fontMetrics();
+ int w = fm.width( (const QString)i18n(" Landscape " ) );
+ int h = fm.height( );
+
+ rb1 = new QRadioButton( i18n("&Landscape"), bgroup );
+ landscape_id = bgroup->id( rb1 );
+ rb2 = new QRadioButton( i18n("P&ortrait"), bgroup );
+ portrait_id = bgroup->id( rb2 );
+ bgroup->setButton( portrait_id );
+
+ connect(bgroup, SIGNAL(clicked(int)), this, SLOT(slOrientChange(int)));
+
+ int rblen = 5+w+12; // 12 for the button?
+ rb1->setGeometry( 5, 6, rblen, h );
+ rb2->setGeometry( 5, 1+h/2+h, rblen, h );
+
+ left->addWidget( bgroup, 2 );
+
+
+ /** Autoselection Box **/
+ d->m_autoSelGroup = new QGroupBox( 1, Horizontal, i18n("Auto-Selection"), frame);
+
+ QHBox *hbox = new QHBox(d->m_autoSelGroup);
+ d->m_cbAutoSel = new QCheckBox( i18n("Active on"), hbox );
+ QToolTip::add( d->m_cbAutoSel, i18n("Check here if you want autodetection\n"
+ "of the document on the preview."));
+
+ /* combobox to select if black or white background */
+ d->m_cbBackground = new QComboBox( hbox );
+ d->m_cbBackground->insertItem(i18n("Black"), BG_ITEM_BLACK );
+ d->m_cbBackground->insertItem(i18n("White"), BG_ITEM_WHITE );
+ connect( d->m_cbBackground, SIGNAL(activated(int) ),
+ this, SLOT( slScanBackgroundChanged( int )));
+
+
+ QToolTip::add( d->m_cbBackground,
+ i18n("Select whether a scan of the empty\n"
+ "scanner glass results in a\n"
+ "black or a white image."));
+ connect( d->m_cbAutoSel, SIGNAL(toggled(bool) ), SLOT(slAutoSelToggled(bool)));
+
+ (void) new QLabel( i18n("scanner background"), d->m_autoSelGroup );
+
+ QLabel *l1= new QLabel( i18n("Thresh&old:"), d->m_autoSelGroup );
+ d->m_sliderThresh = new QSlider( 0, 254, 10, d->m_autoSelThresh, Qt::Horizontal,
+ d->m_autoSelGroup );
+ connect( d->m_sliderThresh, SIGNAL(valueChanged(int)), SLOT(slSetAutoSelThresh(int)));
+ QToolTip::add( d->m_sliderThresh,
+ i18n("Threshold for autodetection.\n"
+ "All pixels higher (on black background)\n"
+ "or smaller (on white background)\n"
+ "than this are considered to be part of the image."));
+ l1->setBuddy(d->m_sliderThresh);
+
+#if 0 /** Dustsize-Slider: No deep impact on result **/
+ (void) new QLabel( i18n("Dust size:"), grBox );
+ d->m_sliderDust = new QSlider( 0, 50, 5, d->m_dustsize, Qt::Horizontal, grBox );
+ connect( d->m_sliderDust, SIGNAL(valueChanged(int)), SLOT(slSetAutoSelDustsize(int)));
+#endif
+
+ /* disable Autoselbox as long as no scanner is connected */
+ d->m_autoSelGroup->setEnabled(false);
+
+ left->addWidget(d->m_autoSelGroup);
+
+ /* Labels for the dimension */
+ QGroupBox *gbox = new QGroupBox( 1, Horizontal, i18n("Selection"), frame, "GROUPBOX" );
+
+ QLabel *l2 = new QLabel( i18n("width - mm" ), gbox );
+ QLabel *l3 = new QLabel( i18n("height - mm" ), gbox );
+
+ connect( this, SIGNAL(setScanWidth(const QString&)),
+ l2, SLOT(setText(const QString&)));
+ connect( this, SIGNAL(setScanHeight(const QString&)),
+ l3, SLOT(setText(const QString&)));
+
+ /* size indicator */
+ QHBox *hb = new QHBox( gbox );
+ (void) new QLabel( i18n( "Size:"), hb );
+ SizeIndicator *indi = new SizeIndicator( hb );
+ QToolTip::add( indi, i18n( "This size field shows how large the uncompressed image will be.\n"
+ "It tries to warn you, if you try to produce huge images by \n"
+ "changing its background color." ));
+ indi->setText( i18n("-") );
+
+ connect( this, SIGNAL( setSelectionSize(long)),
+ indi, SLOT( setSizeInByte (long)) );
+
+ left->addWidget( gbox, 1 );
+
+ left->addStretch( 6 );
+
+ top->activate();
+
+ /* Preset custom Cutting */
+ pre_format_combo->setCurrentItem( ID_CUSTOM );
+ slFormatChange( ID_CUSTOM);
+
+ scanResX = -1;
+ scanResY = -1;
+ pix_per_byte = 1;
+
+ selectionWidthMm = 0.0;
+ selectionHeightMm = 0.0;
+ recalcFileSize();
+}
+
+Previewer::~Previewer()
+{
+ delete d;
+}
+
+bool Previewer::setPreviewImage( const QImage &image )
+{
+ if ( image.isNull() )
+ return false;
+
+ m_previewImage = image;
+ img_canvas->newImage( &m_previewImage );
+
+ return true;
+}
+
+QString Previewer::galleryRoot()
+{
+ QString dir = (KGlobal::dirs())->saveLocation( "data", "ScanImages", true );
+
+ if( !dir.endsWith("/") )
+ dir += "/";
+
+ return( dir );
+
+}
+
+void Previewer::newImage( QImage *ni )
+{
+ /* image canvas does not copy the image, so we hold a copy here */
+ m_previewImage = *ni;
+
+ /* clear the auto detection arrays */
+ d->m_heightSum.resize( 0 );
+ d->m_widthSum.resize( 0 );
+
+ img_canvas->newImage( &m_previewImage );
+ findSelection( );
+}
+
+void Previewer::setScanSize( int w, int h, KRuler::MetricStyle unit )
+{
+ overallWidth = w;
+ overallHeight = h;
+ sizeUnit = unit;
+}
+
+
+void Previewer::slSetDisplayUnit( KRuler::MetricStyle unit )
+{
+ displayUnit = unit;
+}
+
+
+void Previewer::slOrientChange( int id )
+{
+ (void) id;
+ /* Gets either portrait or landscape-id */
+ /* Just read the format-selection and call slFormatChange */
+ slFormatChange( pre_format_combo->currentItem() );
+}
+
+/** Slot called whenever the format selection combo changes. **/
+void Previewer::slFormatChange( int id )
+{
+ QPoint p(0,0);
+ bool lands_allowed;
+ bool portr_allowed;
+ bool setSelection = true;
+ int s_long = 0;
+ int s_short= 0;
+
+ isCustom = false;
+
+ switch( id )
+ {
+ case ID_LETTER:
+ s_long = 294;
+ s_short = 210;
+ lands_allowed = false;
+ portr_allowed = true;
+ break;
+ case ID_CUSTOM:
+ lands_allowed = false;
+ portr_allowed = false;
+ setSelection = false;
+ isCustom = true;
+ break;
+ case ID_A4:
+ s_long = 297;
+ s_short = 210;
+ lands_allowed = false;
+ portr_allowed = true;
+ break;
+ case ID_A5:
+ s_long = 210;
+ s_short = 148;
+ lands_allowed = true;
+ portr_allowed = true;
+ break;
+ case ID_A6:
+ s_long = 148;
+ s_short = 105;
+ lands_allowed = true;
+ portr_allowed = true;
+ break;
+ case ID_9_13:
+ s_long = 130;
+ s_short = 90;
+ lands_allowed = true;
+ portr_allowed = true;
+ break;
+ case ID_10_15:
+ s_long = 150;
+ s_short = 100;
+ lands_allowed = true;
+ portr_allowed = true;
+ break;
+ default:
+ lands_allowed = true;
+ portr_allowed = true;
+ setSelection = false;
+ break;
+ }
+
+ rb1->setEnabled( lands_allowed );
+ rb2->setEnabled( portr_allowed );
+
+ int format_id = bgroup->id( bgroup->selected() );
+ if( !lands_allowed && format_id == landscape_id )
+ {
+ bgroup->setButton( portrait_id );
+ format_id = portrait_id;
+ }
+ /* Convert the new dimension to a new QRect and call slot in canvas */
+ if( setSelection )
+ {
+ QRect newrect;
+ newrect.setRect( 0,0, p.y(), p.x() );
+
+ if( format_id == portrait_id )
+ { /* Portrait Mode */
+ p = calcPercent( s_short, s_long );
+ kdDebug(29000) << "Now is portrait-mode" << endl;
+ }
+ else
+ { /* Landscape-Mode */
+ p = calcPercent( s_long, s_short );
+ }
+
+ newrect.setWidth( p.x() );
+ newrect.setHeight( p.y() );
+
+ img_canvas->newRectSlot( newrect );
+ }
+}
+
+/* This is called when the user fiddles around in the image.
+ * This makes the selection custom-sized immediately.
+ */
+void Previewer::slCustomChange( void )
+{
+ if( isCustom )return;
+ pre_format_combo->setCurrentItem(ID_CUSTOM);
+ slFormatChange( ID_CUSTOM );
+}
+
+
+void Previewer::slNewScanResolutions( int x, int y )
+{
+ kdDebug(29000) << "got new Scan Resolutions: " << x << "|" << y << endl;
+ scanResX = x;
+ scanResY = y;
+
+ recalcFileSize();
+}
+
+
+/* This slot is called with the new dimension for the selection
+ * in values between 0..1000. It emits signals, that redraw the
+ * size labels.
+ */
+void Previewer::slNewDimen(QRect r)
+{
+ if( r.height() > 0)
+ selectionWidthMm = (overallWidth / 1000 * r.width());
+ if( r.width() > 0)
+ selectionHeightMm = (overallHeight / 1000 * r.height());
+
+ QString s;
+ s = i18n("width %1 mm").arg( int(selectionWidthMm));
+ emit(setScanWidth(s));
+
+ kdDebug(29000) << "Setting new Dimension " << s << endl;
+ s = i18n("height %1 mm").arg(int(selectionHeightMm));
+ emit(setScanHeight(s));
+
+ recalcFileSize( );
+
+}
+
+void Previewer::recalcFileSize( void )
+{
+ /* Calculate file size */
+ long size_in_byte = 0;
+ if( scanResY > -1 && scanResX > -1 )
+ {
+ double w_inch = ((double) selectionWidthMm) / 25.4;
+ double h_inch = ((double) selectionHeightMm) / 25.4;
+
+ int pix_w = int( w_inch * double( scanResX ));
+ int pix_h = int( h_inch * double( scanResY ));
+
+ size_in_byte = pix_w * pix_h / pix_per_byte;
+ }
+
+ emit( setSelectionSize( size_in_byte ));
+}
+
+
+QPoint Previewer::calcPercent( int w_mm, int h_mm )
+{
+ QPoint p(0,0);
+ if( overallWidth < 1.0 || overallHeight < 1.0 ) return( p );
+
+ if( sizeUnit == KRuler::Millimetres ) {
+ p.setX( static_cast<int>(1000.0*w_mm / overallWidth) );
+ p.setY( static_cast<int>(1000.0*h_mm / overallHeight) );
+ } else {
+ kdDebug(29000) << "ERROR: Only mm supported yet !" << endl;
+ }
+ return( p );
+
+}
+
+void Previewer::slScaleToWidth()
+{
+ if( img_canvas )
+ {
+ img_canvas->handle_popup( ImageCanvas::ID_FIT_WIDTH );
+ }
+}
+
+void Previewer::slScaleToHeight()
+{
+ if( img_canvas )
+ {
+ img_canvas->handle_popup( ImageCanvas::ID_FIT_HEIGHT);
+ }
+}
+
+void Previewer::slConnectScanner( KScanDevice *scan )
+{
+ kdDebug(29000) << "Connecting scan device!" << endl;
+ d->m_scanner = scan;
+
+ if( scan )
+ {
+ /* Enable the by-default disabled autoselection group */
+ d->m_autoSelGroup->setEnabled(true);
+ QString h;
+
+ h = scan->getConfig( CFG_AUTOSEL_DO, QString("unknown") );
+ if( h == QString("on") )
+ d->m_cbAutoSel->setChecked(true);
+ else
+ d->m_cbAutoSel->setChecked(false);
+
+ QString isWhite = d->m_scanner->getConfig( CFG_SCANNER_EMPTY_BG, "unknown" );
+
+ h = scan->getConfig( CFG_AUTOSEL_DUSTSIZE, QString("5") );
+ d->m_dustsize = h.toInt();
+
+ QString thresh = DEF_THRESH_BLACK; /* for black */
+ if( isWhite.lower() == "yes" )
+ thresh = DEF_THRESH_WHITE;
+
+ h = scan->getConfig( CFG_AUTOSEL_THRESH, thresh );
+ d->m_sliderThresh->setValue( h.toInt() );
+ }
+}
+
+void Previewer::slSetScannerBgIsWhite( bool b )
+{
+ d->m_bgIsWhite = b;
+
+ if( d->m_scanner )
+ {
+ if( b ) // The background _is_ white
+ {
+ d->m_cbBackground->setCurrentItem( BG_ITEM_WHITE );
+ }
+ else
+ {
+ d->m_cbBackground->setCurrentItem( BG_ITEM_BLACK );
+ }
+
+ d->m_scanner->slStoreConfig( CFG_SCANNER_EMPTY_BG, b ? QString("Yes") : QString("No"));
+ }
+}
+
+/**
+ * reads the scanner dependant config file through the m_scanner pointer.
+ * If a value for the scanner is not yet known, the function starts up a
+ * popup and asks the user. The result is stored.
+ */
+void Previewer::checkForScannerBg()
+{
+ if( d->m_scanner ) /* Is the scan device already known? */
+ {
+ QString isWhite = d->m_scanner->getConfig( CFG_SCANNER_EMPTY_BG, "unknown" );
+ bool goWhite = false;
+ if( isWhite == "unknown" )
+ {
+ /* not yet known, should ask the user. */
+ kdDebug(29000) << "Dont know the scanner background yet!" << endl;
+
+ goWhite = ( KMessageBox::questionYesNo( this,
+ i18n("The autodetection of images on the preview depends on the background color of the preview image (Think of a preview of an empty scanner).\nPlease select whether the background of the preview image is black or white"),
+ i18n("Image Autodetection"),
+ i18n("White"), i18n("Black") ) == KMessageBox::Yes );
+ kdDebug(29000) << "User said " << isWhite << endl;
+
+ }
+ else
+ {
+ if( isWhite.lower() == "yes" )
+ goWhite = true;
+ }
+
+ /* remember value */
+ slSetScannerBgIsWhite( goWhite );
+ }
+}
+
+void Previewer::slScanBackgroundChanged( int indx )
+{
+ slSetScannerBgIsWhite( indx == BG_ITEM_WHITE );
+}
+
+void Previewer::slAutoSelToggled(bool isOn )
+{
+ if( isOn )
+ checkForScannerBg();
+
+ if( d->m_cbAutoSel )
+ {
+ QRect r = img_canvas->sel();
+
+ kdDebug(29000) << "The rect is " << r.width() << " x " << r.height() << endl;
+ d->m_doAutoSelection = isOn;
+
+ /* Store configuration */
+ if( d->m_scanner )
+ {
+ d->m_scanner->slStoreConfig( CFG_AUTOSEL_DO,
+ isOn ? "on" : "off" );
+ }
+
+ if( isOn && r.width() < 2 && r.height() < 2) /* There is no selection yet */
+ {
+ /* if there is already an image, check, if the bg-color is set already */
+ if( img_canvas->rootImage() )
+ {
+ kdDebug(29000) << "No selection -> try to find one!" << endl;
+
+ findSelection();
+ }
+
+ }
+ }
+ if( d->m_sliderThresh )
+ d->m_sliderThresh->setEnabled(isOn);
+ if( d->m_sliderDust )
+ d->m_sliderDust->setEnabled(isOn);
+ if( d->m_cbBackground )
+ d->m_cbBackground->setEnabled(isOn);
+
+}
+
+
+void Previewer::slSetAutoSelThresh(int t)
+{
+ d->m_autoSelThresh = t;
+ kdDebug(29000) << "Setting threshold to " << t << endl;
+ if( d->m_scanner )
+ d->m_scanner->slStoreConfig( CFG_AUTOSEL_THRESH, QString::number(t) );
+ findSelection();
+}
+
+void Previewer::slSetAutoSelDustsize(int dSize)
+{
+ d->m_dustsize = dSize;
+ kdDebug(29000) << "Setting dustsize to " << dSize << endl;
+ findSelection();
+}
+
+/**
+ * This method tries to find a selection on the preview image automatically.
+ * It uses the image of the preview image canvas, the previewer global
+ * threshold setting and a dustsize.
+ **/
+void Previewer::findSelection( )
+{
+ kdDebug(29000) << "Searching Selection" << endl;
+
+ kdDebug(29000) << "Threshold: " << d->m_autoSelThresh << endl;
+ kdDebug(29000) << "dustsize: " << d->m_dustsize << endl;
+ kdDebug(29000) << "isWhite: " << d->m_bgIsWhite << endl;
+
+
+ if( ! d->m_doAutoSelection ) return;
+ int line;
+ int x;
+ const QImage *img = img_canvas->rootImage();
+ if( ! img ) return;
+
+ long iWidth = img->width();
+ long iHeight = img->height();
+
+ QMemArray<long> heightSum;
+ QMemArray<long> widthSum;
+
+ kdDebug(29000)<< "Preview size is " << iWidth << "x" << iHeight << endl;
+
+ if( (d->m_heightSum).size() == 0 && (iHeight>0) )
+ {
+ kdDebug(29000) << "Starting to fill Array " << endl;
+ QMemArray<long> heightSum(iHeight);
+ QMemArray<long> widthSum(iWidth);
+ heightSum.fill(0);
+ widthSum.fill(0);
+
+ kdDebug(29000) << "filled Array with zero " << endl;
+
+ for( line = 0; line < iHeight; line++ )
+ {
+
+ for( x = 0; x < iWidth; x++ )
+ {
+ int gray = qGray( img->pixel( x, line ));
+ // kdDebug(29000) << "Gray-Value at line " << gray << endl;
+ Q_ASSERT( line < iHeight );
+ Q_ASSERT( x < iWidth );
+ int hsum = heightSum.at(line);
+ int wsum = widthSum.at(x);
+
+ heightSum[line] = hsum+gray;
+ widthSum [x] = wsum+gray;
+ }
+ heightSum[line] = heightSum[line]/iWidth;
+ }
+ /* Divide by amount of pixels */
+ kdDebug(29000) << "Resizing now" << endl;
+ for( x = 0; x < iWidth; x++ )
+ widthSum[x] = widthSum[x]/iHeight;
+
+ kdDebug(29000) << "Filled Arrays successfully" << endl;
+ d->m_widthSum = widthSum;
+ d->m_heightSum = heightSum;
+ }
+ /* Now try to find values in arrays that have grayAdds higher or lower
+ * than threshold */
+#if 0
+ /* debug output */
+ {
+ QFile fi( "/tmp/thheight.dat");
+ if( fi.open( IO_ReadWrite ) ) {
+ QTextStream str( &fi );
+
+ str << "# height ##################" << endl;
+ for( x = 0; x < iHeight; x++ )
+ str << x << '\t' << d->m_heightSum[x] << endl;
+ fi.close();
+ }
+ }
+ QFile fi1( "/tmp/thwidth.dat");
+ if( fi1.open( IO_ReadWrite ))
+ {
+ QTextStream str( &fi1 );
+ str << "# width ##################" << endl;
+ str << "# " << iWidth << " points" << endl;
+ for( x = 0; x < iWidth; x++ )
+ str << x << '\t' << d->m_widthSum[x] << endl;
+
+ fi1.close();
+ }
+#endif
+ int start = 0;
+ int end = 0;
+ QRect r;
+
+ /** scale to 0..1000 range **/
+ start = 0;
+ end = 0;
+ imagePiece( d->m_heightSum, start, end ); // , d->m_threshold, d->m_dustsize, false );
+
+ r.setTop( 1000*start/iHeight );
+ r.setBottom( 1000*end/iHeight);
+ // r.setTop( start );
+ // r.setBottom( end );
+
+ start = 0;
+ end = 0;
+ imagePiece( d->m_widthSum, start, end ); // , d->m_threshold, d->m_dustsize, false );
+ r.setLeft( 1000*start/iWidth );
+ r.setRight( 1000*end/iWidth );
+ // r.setLeft( start );
+ // r.setRight( end );
+
+ kdDebug(29000) << " -- Autodetection -- " << endl;
+ kdDebug(29000) << "Area top " << r.top() << endl;
+ kdDebug(29000) << "Area left" << r.left() << endl;
+ kdDebug(29000) << "Area bottom " << r.bottom() << endl;
+ kdDebug(29000) << "Area right " << r.right() << endl;
+ kdDebug(29000) << "Area width " << r.width() << endl;
+ kdDebug(29000) << "Area height " << r.height() << endl;
+
+ img_canvas->newRectSlot( r );
+ slCustomChange();
+}
+
+
+/*
+ * returns an Array containing the
+ */
+bool Previewer::imagePiece( QMemArray<long> src, int& start, int& end )
+{
+ for( uint x = 0; x < src.size(); x++ )
+ {
+ if( !d->m_bgIsWhite )
+ {
+ /* pixelvalue needs to be higher than threshold, white background */
+ if( src[x] > d->m_autoSelThresh )
+ {
+ /* Ok this pixel could be the start */
+ int iStart = x;
+ int iEnd = x;
+ x++;
+ while( x < src.size() && src[x] > d->m_autoSelThresh )
+ {
+ x++;
+ }
+ iEnd = x;
+
+ int delta = iEnd-iStart;
+
+ if( delta > d->m_dustsize && end-start < delta )
+ {
+ start = iStart;
+ end = iEnd;
+ }
+ }
+ }
+ else
+ {
+ /* pixelvalue needs to be lower than threshold, black background */
+ if( src[x] < d->m_autoSelThresh )
+ {
+ int iStart = x;
+ int iEnd = x;
+ x++;
+ while( x < src.size() && src[x] < d->m_autoSelThresh )
+ {
+ x++;
+ }
+ iEnd = x;
+
+ int delta = iEnd-iStart;
+
+ if( delta > d->m_dustsize && end-start < delta )
+ {
+ start = iStart;
+ end = iEnd;
+ }
+ }
+ }
+ }
+ return (end-start)>0;
+}
+
+#include "previewer.moc"