You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegraphics/libkscan/previewer.cpp

872 lines
25 KiB

/* This file is part of the KDE Project
Copyright (C) 2000 Klaas Freitag <freitag@suse.de>
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 <tqlabel.h>
#include <tqfontmetrics.h>
#include <tqhbox.h>
#include <tqtooltip.h>
#include <tqpopupmenu.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqcombobox.h>
#include <tqradiobutton.h>
#include <tqgroupbox.h>
#include <tqlayout.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 <tqslider.h>
#include <tqcheckbox.h>
#include <kconfig.h>
#include <tqbuttongroup.h>
#include <tqvbuttongroup.h>
#include <kmessagebox.h>
#include <tqvaluevector.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 */
TQSlider *m_sliderThresh;
TQSlider *m_sliderDust;
TQCheckBox *m_cbAutoSel;
TQComboBox *m_cbBackground;
TQGroupBox *m_autoSelGroup;
KScanDevice *m_scanner;
TQMemArray<long> m_heightSum;
TQMemArray<long> m_widthSum;
};
Previewer::Previewer(TQWidget *parent, const char *name )
: TQWidget(parent,name)
{
d = new PreviewerPrivate();
// beautification to look like the left scanparams widget in the dialog
TQHBoxLayout *htop = new TQHBoxLayout( this );
TQFrame *frame = new TQFrame( this );
frame->setFrameStyle( TQFrame::Panel | TQFrame::Raised );
frame->setLineWidth( 1 );
htop->addWidget( frame );
TQVBoxLayout *top = new TQVBoxLayout( frame, KDialog::marginHint(), KDialog::spacingHint() );
tqlayout = new TQHBoxLayout( KDialog::spacingHint() );
top->addLayout( tqlayout, 9 );
TQVBoxLayout *left = new TQVBoxLayout( KDialog::spacingHint() );
tqlayout->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->tqrepaint();
tqlayout->addWidget( img_canvas, 6 );
/* Actions for the previewer zoom */
KAction *act;
act = new KAction(i18n("Scale to W&idth"), "scaletowidth", CTRL+Key_I,
TQT_TQOBJECT(this), TQT_SLOT( slScaleToWidth()), TQT_TQOBJECT(this), "preview_scaletowidth" );
act->plug( img_canvas->contextMenu());
act = new KAction(i18n("Scale to &Height"), "scaletoheight", CTRL+Key_H,
TQT_TQOBJECT(this), TQT_SLOT( slScaleToHeight()), TQT_TQOBJECT(this), "preview_scaletoheight" );
act->plug( img_canvas->contextMenu());
/*Signals: Control the custom-field and show size of selection */
connect( img_canvas, TQT_SIGNAL(newRect()), this, TQT_SLOT(slCustomChange()));
connect( img_canvas, TQT_SIGNAL(newRect(TQRect)), this, TQT_SLOT(slNewDimen(TQRect)));
/* Stuff for the preview-Notification */
left->addWidget( new TQLabel( i18n("<B>Preview</B>"), frame ), 1);
// Create a button group to contain buttons for Portrait/Landscape
bgroup = new TQVButtonGroup( i18n("Scan Size"), frame );
// -----
pre_format_combo = new TQComboBox( 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, TQT_SIGNAL(activated (int)),
this, TQT_SLOT( slFormatChange(int)));
left->addWidget( pre_format_combo, 1 );
/** Potrait- and Landscape Selector **/
TQFontMetrics fm = bgroup->fontMetrics();
int w = fm.width( (const TQString)i18n(" Landscape " ) );
int h = fm.height( );
rb1 = new TQRadioButton( i18n("&Landscape"), bgroup );
landscape_id = bgroup->id( rb1 );
rb2 = new TQRadioButton( i18n("P&ortrait"), bgroup );
portrait_id = bgroup->id( rb2 );
bgroup->setButton( portrait_id );
connect(bgroup, TQT_SIGNAL(clicked(int)), this, TQT_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 TQGroupBox( 1,Qt::Horizontal, i18n("Auto-Selection"), frame);
TQHBox *hbox = new TQHBox(d->m_autoSelGroup);
d->m_cbAutoSel = new TQCheckBox( i18n("Active on"), hbox );
TQToolTip::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 TQComboBox( hbox );
d->m_cbBackground->insertItem(i18n("Black"), BG_ITEM_BLACK );
d->m_cbBackground->insertItem(i18n("White"), BG_ITEM_WHITE );
connect( d->m_cbBackground, TQT_SIGNAL(activated(int) ),
this, TQT_SLOT( slScanBackgroundChanged( int )));
TQToolTip::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, TQT_SIGNAL(toggled(bool) ), TQT_SLOT(slAutoSelToggled(bool)));
(void) new TQLabel( i18n("scanner background"), d->m_autoSelGroup );
TQLabel *l1= new TQLabel( i18n("Thresh&old:"), d->m_autoSelGroup );
d->m_sliderThresh = new TQSlider( 0, 254, 10, d->m_autoSelThresh, Qt::Horizontal,
d->m_autoSelGroup );
connect( d->m_sliderThresh, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slSetAutoSelThresh(int)));
TQToolTip::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 TQLabel( i18n("Dust size:"), grBox );
d->m_sliderDust = new TQSlider( 0, 50, 5, d->m_dustsize, Qt::Horizontal, grBox );
connect( d->m_sliderDust, TQT_SIGNAL(valueChanged(int)), TQT_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 */
TQGroupBox *gbox = new TQGroupBox( 1,Qt::Horizontal, i18n("Selection"), frame, "GROUPBOX" );
TQLabel *l2 = new TQLabel( i18n("width - mm" ), gbox );
TQLabel *l3 = new TQLabel( i18n("height - mm" ), gbox );
connect( this, TQT_SIGNAL(setScanWidth(const TQString&)),
l2, TQT_SLOT(setText(const TQString&)));
connect( this, TQT_SIGNAL(setScanHeight(const TQString&)),
l3, TQT_SLOT(setText(const TQString&)));
/* size indicator */
TQHBox *hb = new TQHBox( gbox );
(void) new TQLabel( i18n( "Size:"), hb );
SizeIndicator *indi = new SizeIndicator( hb );
TQToolTip::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, TQT_SIGNAL( setSelectionSize(long)),
indi, TQT_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 TQImage &image )
{
if ( image.isNull() )
return false;
m_previewImage = image;
img_canvas->newImage( &m_previewImage );
return true;
}
TQString Previewer::galleryRoot()
{
TQString dir = (KGlobal::dirs())->saveLocation( "data", "ScanImages", true );
if( !dir.endsWith("/") )
dir += "/";
return( dir );
}
void Previewer::newImage( TQImage *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 )
{
TQPoint 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 TQRect and call slot in canvas */
if( setSelection )
{
TQRect 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(TQRect r)
{
if( r.height() > 0)
selectionWidthMm = (overallWidth / 1000 * r.width());
if( r.width() > 0)
selectionHeightMm = (overallHeight / 1000 * r.height());
TQString s;
s = i18n("width %1 mm").tqarg( int(selectionWidthMm));
emit(setScanWidth(s));
kdDebug(29000) << "Setting new Dimension " << s << endl;
s = i18n("height %1 mm").tqarg(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 ));
}
TQPoint Previewer::calcPercent( int w_mm, int h_mm )
{
TQPoint 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);
TQString h;
h = scan->getConfig( CFG_AUTOSEL_DO, TQString("unknown") );
if( h == TQString("on") )
d->m_cbAutoSel->setChecked(true);
else
d->m_cbAutoSel->setChecked(false);
TQString isWhite = d->m_scanner->getConfig( CFG_SCANNER_EMPTY_BG, "unknown" );
h = scan->getConfig( CFG_AUTOSEL_DUSTSIZE, TQString("5") );
d->m_dustsize = h.toInt();
TQString 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 ? TQString("Yes") : TQString("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? */
{
TQString 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 )
{
TQRect 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, TQString::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 TQImage *img = img_canvas->rootImage();
if( ! img ) return;
long iWidth = img->width();
long iHeight = img->height();
TQMemArray<long> heightSum;
TQMemArray<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;
TQMemArray<long> heightSum(iHeight);
TQMemArray<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 = tqGray( 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 */
{
TQFile fi( "/tmp/thheight.dat");
if( fi.open( IO_ReadWrite ) ) {
TQTextStream str( &fi );
str << "# height ##################" << endl;
for( x = 0; x < iHeight; x++ )
str << x << '\t' << d->m_heightSum[x] << endl;
fi.close();
}
}
TQFile fi1( "/tmp/thwidth.dat");
if( fi1.open( IO_ReadWrite ))
{
TQTextStream 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;
TQRect 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( TQMemArray<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"