Display resulting image while scanning in a tab of libksane's KSaneWidget
Needs ReviewPublic

Authored by trufanov on Jan 5 2019, 11:56 PM.



That's a new feature for KSaneWidget, that is turned off by default and should be enabled via UI (SkanLite).
It addresses the following problem.

Currently KSaneWidget has preview and scan buttons.
If you click on preview - whole scanning area will be scanned with small dpi (usually 50dpi). And then displayed in GUI. The displayed scanner area could be used to select actual page in it and perform a real scan of selected subarea with a good dpi (300+ dpi). Selection of the subareas is a great option that allows to minimize page scanning time.

If you click scan - you'll just subsequently scan all subareas, or whole scanning area if no subareas were selected. But you'll not see the results. Result can't be displayed in preview window instead of preview as one of it's main functions is to let user select subareas and result may be subarea by itself. There is an option that shows you a result in pop up dialog just before saving, but this interrupts the scanning process and waits for user response.

My scanning process is usually like that: Put a book in scanner, align it to one of scanner's corners. Do preview, select scanning area, scan. Turn the page, align book to the same corner, scan. Etc. I don't see the resulting images. Otherwise I would need to open last saved file every time or enable "preview before save" option and get interrupted after each scan. I rely on fact that book pages are all of the same size and all content will be scanned if I place book in the same position. So I'm scanning in "blind" mode without actually seeing results.

But there are cases when I want to fast check last scanning result even if i'm sure all content is inside subarea:

  1. I forgot if I already turned the pages or accidentally closed the book and want to recall last scanned page no.
  2. I've changed some scanning settings (color/grayscale or dpi) and want to check if I managed to achieve expected quality.
  3. I want to check if there aren't any hairs, dirt, small piece of paper on scanner's glass that could get there after pages turn.
  4. I want to check how curvy is text that is closer to the book's spine. It depends on strength of pressure on the book and could change in case of page is in a middle of the book or at beginning.


So I need at least a button "Show me last scan" that I can click when I want to check last result.
But I decide to make a bit better function - display last scan automatically in widget's UI. First idea was to copy last scanned image to respecting area of displayed preview image. But it's inconsistent as UI will display some chimera made of old image and new images. And as preview is 50 dpi and actual scans of subareas are mostly 300+ dpi this will require some scaling that require noticeable cpu time. Thus I end up with following solution:

If function is enabled widget will display a vertical tab near preview image with tabs: "Preview" and "Current Scan". In case second is clicker KSaneImageViewer is switched to display another QImage. It's area selection functionality is disabled as there is no sense to select subareas in subarea. And this QImage isn't just loaded from latest saved scan file but builded dynamically chunk by chunk during scanning in progress as preview image is build. So user'll see the result even before scanning ends.

After turning on this function user experience will be following:
Put a book on scanner, click preview, select pages area in preview image, switch to Current Scan tab, click Scan button - look on actual scanning results at real time. Turn the page, click on scan button again. etc. Need to change selection? Go to preview tab, change selection in it (or even update preview) and get back to Current scan Tab for actual scanning.

This review contains most of the code, but to test it you'll need to enable it via GUI (as it's disabled by default). Thus another patch will be send to Skanlite repository to add required setting in its GUI.

P.S. Feature is switched off by default bcs it requires more RAM than usual. High dpi quality A4 scans may be too big to keep another copy in RAM of old <=1Gb RAM machine without system performance decrease.

Test Plan

Apply patch, apply Skanlite's patch. build both. Launch Skanlite, Switch on "Display last image in separate tab" in its settings.

Diff Detail

R382 KSane Library
Lint Skipped
Unit Tests Skipped
trufanov requested review of this revision.Jan 5 2019, 11:56 PM
trufanov created this revision.
yurchor added a subscriber: yurchor.Jan 6 2019, 7:20 AM

Thanks for fixing these minor typos.


Typo: reqired -> required


Typo: is whole -> if whole


Typo: it always display -> it always displays


Typo: opertions -> operations


Typo: selections opertions -> selection operations


Typo: peritted -> permitted


Typo: peritted -> permitted


Typo: scn -> scan


Typo: regardles -> regardless

trufanov updated this revision to Diff 48806.Jan 6 2019, 4:29 PM

Typos are fixed. Thanks!

sars added a comment.Jan 7 2019, 10:30 AM

I have not had the time to review this properly sorry :(

I have long been thinking that the current monolithic widget design is a bit broken. It does not provide the flexibility to give you just the scan-options or just the preview or build your own rearranged UI.

This feature should IMO be in the application and not in the library, but the current design makes it hard to do that way :(

I'll have a look again when I get the time.

trufanov updated this revision to Diff 52849.Feb 28 2019, 6:31 PM
trufanov retitled this revision from Display last scanned image in tab of libksane's KSaneWidget to Display resulting image while scanning in a tab of libksane's KSaneWidget.

I've checked that diff works after recent updates to the codebase and replaced QTabWidget with QTabBar.
Now ready for review whenever you have a free time for this.

sars added a comment.Mar 2 2019, 1:54 PM


This is a good improvement idea for libksane. :)

Having a separate tab for final-scan and preview is not really optimal. You stated in the description that it would be CPU intensive to scale 300+ dpi images and place them in the selection areas, but if you scan at 300+DPI, you will anyways have to scale the image to make it fit in the tab, so I think it would be best to just scale them enough to place them in the selection areas (the selections can be zoomed in to fill the visible view-port).

So what I would like to have is a new function to set a QImage for the "final-scan-image" for KSaneViewer (KSaneViewer::setSelectionImage(QImage *selectionImg). (setQImage() should be renamed to setBackgroundImage())
The new function would not clear the selections or reset the zoom.

Then in KSaneViewer::drawBackground() you would add a "painter->drawImage(<QRectF>, *d->selectionImg, <QRectF>);" where "<QRectF>" is the rectangle of the active selection.
This selection image would only be drawn if d->selectionImg is not nullptr. (d->selectionImg could be set to nullptr in setBackgroundImage() when a new preview is done)

So now what we need is to get the preview data also from final scans just like you did, but Alexander Volkov started work on unifying the scan threads and his idea was that we would at some point only have one scanning thread class. I would like to continue on that route and remove one of them.

We could still have two instances of that one class, with just different connections. The preview only updates the KSaneViewer background and the "final-scan" instance would update the selection image and be used for the imageReady() signal.

Small side notes: Please use camelCase variable names to follow the KDE Frameworks style guide. Also add, the good, optimizations (d->img->height() to a temporary local variable) in a separate review request so that the relevant changes for this change become more visible.

Thanks for working on this!