Develop & Customize

Insert Images To a Specified Index

By default, when you scan or load images, they are appended. In other words, they are added to the very end of the image array in buffer. However, in some business scenarios, the user might want to insert these new images to a specified index. Unfortunately, Dynamic Web TWAIN doesn't provide a native method for that. The following code snippet shows how it can be done

Insert when acquiring
function acquireToIndex(index) {
    DWObject.IfAppendImage = false;
    DWObject.CurrentImageIndexInBuffer = index;
    DWObject.RegisterEvent('OnBitmapChanged', function (strUpdatedIndex, operationType, sCurrentIndex) {
        if (operationType == 2) { //inserting
            DWObject.CurrentImageIndexInBuffer ++;
        }
    });
    DWObject.AcquireImage();
}
Insert when loading
var bPostLoad = false, newIndices = [];
function loadToIndex(index) {
    bPostLoad = false;
    newIndices = [];
    DWObject.IfAppendImage = false;
    DWObject.CurrentImageIndexInBuffer = index;
    DWObject.RegisterEvent('OnPostLoad', function () {
        bPostLoad = true;
        for (var j = 0; j < newIndices.length / 2; j++)
            if (newIndices[j] != newIndices[newIndices.length - j - 1])
                DWObject.SwitchImage(newIndices[j], newIndices[newIndices.length - j - 1]);
        DWObject.IfAppendImage = true;
    });
    DWObject.RegisterEvent('OnBitmapChanged', function (strUpdatedIndex, operationType, sCurrentIndex) {
        if (operationType == 2) { //inserting
            for (var i = 0; i < newIndices.length; i++)
                newIndices[i] += 1;
            newIndices.push(parseInt(strUpdatedIndex[0]));
        }
    });
    DWObject.LoadImageEx('', 5);
}

Reuse TWAIN Configurations

Custom DataSource Data or CDD refers to all configurations of a device. Many devices support exporting CDD to a file or a base64-encoded string to be used later. By using the same CDD, the same device can always carry out scan jobs with the same configurations. CDD can also be shared among multiple devices to ensure all of them are scanning with the same settings. To use this feature, we have four methods: SetCustomDSData(), SetCustomDSDataEx(), GetCustomDSData() and GetCustomDSDataEx(). The typical steps are

  1. Show the scanner's User Interface and change all the settings necessary.
  2. Perform a scan and remember/save the CDD in the callback of the event OnPostAllTransfers using either GetCustomDSData() or GetCustomDSDataEx().
  3. Later on, when you or any other user who needs to scan with the same settings on the same device (or device of the same model), you can hide the scanner's own interface and simply use the method SetCustomDSDataEx() or SetCustomDSData() to pass the CDD to the device.
Code Snippet
var DWObject = null;
var Base64EncodedDSData = "";
function Dynamsoft_OnReady() {
    DWObject = Dynamsoft.WebTwainEnv.GetWebTwain('dwtcontrolContainer');
    DWObject.RegisterEvent("OnPostAllTransfers", function () {
        Base64EncodedDSData = DWObject.GetCustomDSDataEx();
    });
}
function AcquireImage() {
    DWObject.IfDisableSourceAfterAcquire = true;
    DWObject.SelectSource(function () {
        var OnAcquireImageSuccess, OnAcquireImageFailure;
        OnAcquireImageSuccess = OnAcquireImageFailure = function () {
            DWObject.CloseSource();
        };
        DWObject.OpenSource();
        if (Base64EncodedDSData != "") {
            DWObject.IfShowUI = false;
            DWObject.SetCustomDSDataEx(Base64EncodedDSData);
        } else {
            DWObject.IfShowUI = true;
        }
        DWObject.AcquireImage(OnAcquireImageSuccess, OnAcquireImageFailure);
    }, function () { console.log("Failed to Select A Source!"); });
}

TWAIN Capability Negotiation

How can I set resolution in the X and Y direction separately

With capability negotiation, you can use the capabilities ICAP_XRESOLUTION and ICAP_YRESOLUTION to set resolution in the X and Y direction separately.

Code Snippet

DWObject.SelectSource();
DWObject.OpenSource();
//Set X-RESOLUTION current value.
DWObject.Capability = EnumDWT_Cap.ICAP_XRESOLUTION;
DWObject.CapType = EnumDWT_CapType.TWON_RANGE;
DWObject.CapValue = 300;
if (DWObject.CapSet())
    alert("Successful");
else
    alert("Source doesn't support this capability");
//Set Y-RESOLUTION current value.
DWObject.Capability = EnumDWT_Cap.ICAP_YRESOLUTION;
DWObject.CapType = EnumDWT_CapType.TWON_RANGE;
DWObject.CapValue = 200;
if (DWObject.CapSet())
    alert("Successful");
else
    alert("Source doesn't support this capability");
DWObjet.AcquireImage();

For more information, please refer to How to Perform Capability Negotiation.

How to detect and discard blank pages automatically

If the TWAIN driver of your device supports discarding blank pages, you can use the driver's built-in feature.

You can set the IfShowUI property to true to display the User Interface (UI) of the source and you can check the option there (it normally reads 'discard blank')

If you don't want to show the user interface of the source, you can set IfAutoDiscardBlankpages to true or negotiate the ICAP_AUTODISCARDBLANKPAGES capability in code to discard blank page automatically. Please NOTE that this property or capability only works if the scanner itself supports the feature (on the hardware level).

Code Snippet

DWObject.SelectSource();
DWObject.OpenSource;
DWObject.IfShowUI = false;
//*Use the property
DWObject.IfAutoDiscardBlankpages = true;
//*Use capability negotiation
DWObject.Capability = EnumDWT_Cap.ICAP_AUTODISCARDBLANKPAGES;
DWObject.CapType = EnumDWT_CapType.TWON_ONEVALUE;
DWObject.CapValue = -1;//Auto
if(DWObject.CapSet){
   alert("Successful!");
}
DWObject.AcquireImage();

If the scanner itself doesn't support discarding blank pages, you can also use the method IsBlankImageExpress() to do this as a workaround. To detect and discard blank pages automatically, you can do it in the OnPostTransfer event which fires after each transfer.

Code Snippet

function DWObject_OnPostTransfer() {
    DWObject.BlankImageMaxStdDev = 20;
    if (DWObject.IsBlankImageExpress(DWObject.CurrentImageIndexInBuffer)) {
        DWObject.RemoveImage(DWObject.CurrentImageIndexInBuffer);
    }
}

NOTE: In many cases, the scanned blank image may come with some noises which would affect the result returned by IsBlankImageExpress. To improve the result, you may adjust the value of BlankImageMaxStdDev Property. The default value is 1 (0 means single-color image). Thus, by increasing the value a little bit (e.g. to 20), noises on images are ignored so a blank image can be detected faster.

For more information, please refer to How to Perform Capability Negotiation.

How to rotate the scanned image data prior to transfer

With capability negotiation, you can use the capability ICAP_ROTATION to rotate the scanned image data before it's transferred.

Note: Before using these methods, please make sure that the driver of your device supports automatic rotating.

Code Snippet

function btnScan()
{
    DWObject.SelectSource();
    DWObject.OpenSource();
    DWObject.MaxImagesInBuffer = 4;

   /*============== rotate ==============*/
    DWObject.Capability = EnumDWT_Cap.ICAP_ROTATION;
    DWObject.CapType  =  EnumDWT_CapType.TWON_ONEVALUE;
    DWObject.CapValue = 270; //270 degree rotation
        if (DWObject.CapSet())
            alert("Successful");
        else
            alert("Source doesn't support this capability");
    DWObject.IfDisableSourceAfterAcquire = true;
    DWObject.AcquireImage();
}

For more information, please refer to How to Perform Capability Negotiation.

How to use custom capabilities of your TWAIN device

To use a custom capability of your TWAIN driver, you need to know what the capability code is first. You can follow the steps below:

  • Install the TWAIN sample application.

  • Use the TWAIN Sample App to open the source and then check what the hexadecimal value of the capability is.

TWAIN Sample App1 TWAIN Sample App2

  • As an example, the code 0x8001 is for the highlighted custom capability above. Now we can use the following code to negotiate the capability.

Code Snippet

DWObject.SelectSource();
DWObject.OpenSource();
DWObject.Capability = 0x8001;
DWObject.CapType = 5; //TWON_ONEVALUE
DWObject.CapValue = 1;
if (DWObject.CapSet())
    alert("successful");
else
    alert("Source doesn't support this capatiblity");

For more information, please refer to How to Perform Capability Negotiation.


Details on the Upload Feature

How to upload images directly to Database

To upload images to the server and save them directly into database, you simply need to rewrite the action page on the server. The following is an example written in C# and uses MSSQL as the database

try {
    int iFileLength;
    HttpFileCollection files = HttpContext.Current.Request.Files;
    HttpPostedFile uploadfile = files["RemoteFile"];
    string strImageName = uploadfile.FileName;

    iFileLength = uploadfile.ContentLength;
    Byte[] inputBuffer = new Byte[iFileLength];
    System.IO.Stream inputStream;
    inputStream = uploadfile.InputStream;
    inputStream.Read(inputBuffer, 0, iFileLength);
    inputStream.Close();
    string sql_insertData = "INSERT INTO " + tableName + " (document_name, document_data) VALUES (@document_name, @document_data)";
    using(System.Data.SqlClient.SqlCommand sqlcmd_insertData = new System.Data.SqlClient.SqlCommand(sql_insertData, Connection)) {
        sqlcmd_insertData.Parameters.Add("@document_data", System.Data.SqlDbType.Binary, iFileLength).Value = inputBuffer;
        sqlcmd_insertData.Parameters.Add("@document_name", System.Data.SqlDbType.VarChar, 255).Value = strImageName;
        sqlcmd_insertData.ExecuteScalar();
    }
    Connection.Close();
} catch (Exception) {}

If you use languges like PHP, JSP, etc., you can check out sample scripts as part of the official upload sample.

How to upload images through methods like AJAX instead of built-in methods

Basically, the workflow would be like this:

  1. Scan images to the control.
  2. Use the method ConvertToBase64() or ConvertToBlob() to convert the images in the buffer to a Base64-encoded string or a Blob object.
  3. Upload the string or the Blob to the server

We'll use the method ConvertToBase64() as an example in the code sample below. Note that C# is used on the server-side.

Client-Side
// Select all images
var aryIndices = [];
for (var i = 0; i < DWObject.HowManyImagesInBuffer; i++) {
    aryIndices.push(i);
}

DWObject.ConvertToBase64(aryIndices, EnumDWT_ImageType.IT_PDF, asyncSuccessFunc, asyncFailureFunc);

function asyncSuccessFunc(result) {
    var param = encodeURIComponent("ImageName") + "=" + encodeURIComponent("uploadedImages.pdf") + "&" + encodeURIComponent("RemoteFile") + "=" + encodeURIComponent(result);
    //You can upload the image data from here
    makeRequest(strActionPage, param, false);
}

function asyncFailureFunc(errorCode, errorString) {
    alert("ErrorCode: " + errorCode + "\r" + "ErrorString:" + errorString);
}

//AJAX
function makeRequest(url, parameter, flg) {
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest(); // Set up the request.
    } else {
        if (window.ActiveXObject) {
            try {
                xhr = new ActiveXObject("MSXML2.XMLHTTP.3.0");
            } catch (ex) {
                alert(ex);
            }
        }
    }
    if (xhr) {
        if (flg) {
            xhr.open("GET", url, true); // Open the connection.
            xhr.onreadystatechange = requestresultCat;
            xhr.setRequestHeader("If-Modified-Since", "0");
            xhr.send(null);
        } else {
            xhr.open("POST", url, false);
            if (parameter != null) {
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.send(parameter); // Send the Data.
            } else {
                xhr.send(null);
            }
        }
    } else {
        AppendMessage("&lt;b&gt;Sorry, but I couldn't create an XMLHttpRequest!&lt;/b&gt; ");
    }
}

function requestresult() {
    if (xhr.readyState == 4) {
        if (xhr.status == 200) { // File(s) uploaded.
            var outMsg;
            if (xhr.responseXML & amp; & amp; xhr.responseXML.documentElement) {
                outMsg = xhr.responseXML;
                alert(xhr.responseText);
            }
        }
    }
}
Server-Side
try {
    string imageName = HttpContext.Current.Request.Form["ImageName"];
    string imageData = HttpContext.Current.Request.Form["RemoteFile"];
    string Path = System.Web.HttpContext.Current.Request.MapPath(".") + "/ImageScanned/";
    if (!Directory.Exists(Path)) {
        Directory.CreateDirectory(Path);
    }
    string outputFileName = Path + imageName;
    // Convert the Base64 UUEncoded input into binary output.
    byte[] binaryData;
    try {
        binaryData = System.Convert.FromBase64String(imageData);
    } catch (System.ArgumentNullException) {
        System.Console.WriteLine("Base 64 string is null.");
        return;
    } catch (System.FormatException) {
        System.Console.WriteLine("Base 64 string length is not " +
            "4 or is not an even multiple of 4.");
        return;
    }

    // Write out the decoded data.
    System.IO.FileStream outFile;
    try {
        outFile = new System.IO.FileStream(outputFileName,
            System.IO.FileMode.Create,
            System.IO.FileAccess.Write);
        outFile.Write(binaryData, 0, binaryData.Length);
        outFile.Close();
    } catch (System.Exception exp) {}
} catch (Exception exc) {}
How to upload multiple files at a time
Scenario

After scanning multiple files, you might want to upload them one by one as individual images. Before version 13.1, you have to call the upload method(s) multiple times. In v13.1+, you can do this in one go.

Solution

Use the methods ConvertToBlob() and HTTPUpload().

Steps:

  • In JavaScript, write code similar to the following
var i = 0;
DWObject.ClearAllHTTPFormField();
DWObject.SetHTTPFormField("UploadedImagesCount", DWObject.HowManyImagesInBuffer);

function asyncFailureFunc(errorCode, errorString) {
    alert("ErrorCode: " + errorCode + "\r" + "ErrorString:" + errorString);
}

var convertImage = function (_index) {
    DWObject.ConvertToBlob([_index], EnumDWT_ImageType.IT_JPG,
        function (result) {
            DWObject.SetHTTPFormField('image_' + _index, result, 'JPG_image_' + _index);
            i++;
            if (i < DWObject.HowManyImagesInBuffer) {
                convertImage(i);
            } else {
                DWObject.HTTPUpload("http://yourserver/youractionpage.aspx", function () {
                    console.log('success')
                }, function () {
                    console.log('failure');
                });
            }
        }, asyncFailureFunc);
};

convertImage(0);
  • On the server, add an action page to process the uploaded data
<%@ Page Language="C#" %>

<%
    try
    {
        String strImageName;
        String strInfo = HttpContext.Current.Request["UploadedImagesCount"];
        short uploadedImagesCount = Convert.ToInt16(strInfo);
        HttpFileCollection files = HttpContext.Current.Request.Files;
        for (short i = 0; i < uploadedImagesCount; i++)
        {
            HttpPostedFile uploadfile = files["image_" + i.ToString()];
            strImageName = uploadfile.FileName;
            uploadfile.SaveAs(Server.MapPath(".") + "\\UploadedImages\\" + strImageName + ".jpg");
        }
    }
    catch
    {}
%>
How to use FileUploader to do the upload

In Dynamic Web TWAIN Version 14.0, we added a new upload module called FileUploader to handle upload jobs. The following shows how to use this new module to do the upload.

Step:

  • Reference the dynamsoft.upload.js file
<script type="text/javascript" src="Resources/addon/dynamsoft.upload.js">
  • Initiate the FileUploader module
var dsUploadManager;
Dynamsoft.FileUploader.Init('', function(obj) {
    dsUploadManager = obj;
    },
    function(errorcode, errorstring){
        alert(errorstring);
    }
);
  • Create an job and execute it
var job = dsUploadManager.CreateJob();
dsUploadManager.Run(job);

Full sample

var fileUploaderManager;

Dynamsoft.FileUploader.Init("", onInitSuccess, onInitFailure);

function onInitSuccess(objFileUploader) {
    fileUploaderManager = objFileUploader;
}

function onInitFailure(errorCode, errorString) {
    alert('Init failed: ' + errorString);
}

function UploadFile() {
    var job = fileUploaderManager.CreateJob();
    job.ServerUrl = 'http://yourserver/youractionpage.aspx';
    DWObject.GenerateURLForUploadData([0], EnumDWT_ImageType.IT_JPG, function(res) {
        job.SourceValue.Add(res, "sample.jpg");
        job.SourceValue.Add("D:\\test1.jpg", "test.jpg");
        job.OnUploadTransferPercentage = FileUpload_OnUploadTransferPercentage;
        job.OnRunSuccess = FileUpload_OnRunSuccess;
        job.OnRunFailure = FileUpload_OnRunFailure;
        fileUploaderManager.Run(job);
    }, function(errorCode, errorString) {console.log(errorString);});
}

function FileUpload_OnUploadTransferPercentage(job, sPercentage) {
    console.log(sPercentage);
}

function FileUpload_OnRunFailure(job, errorCode, errorString) {
    alert(errorString);
}

function FileUpload_OnRunSuccess(job) {
    alert(' upload completed! ');
}

Details on the Download Feature

How to download images directly from Database
Scenario

Sometimes you may need to download an image file from the server but that file exists only in the database.

Solution

With a proper action page DownloadFromDB.aspx, the method HTTPDownloadEx() can fulfill the requirement.

Steps

  • On the server, add an action page to fetch the image data from the database and send it back.

Here we take C# and MSSQL as an example and assume the image to download is a JPEG image and can be fetched by its ID (iImageID).

string strConnString = "Server=***\\SQLEXPRESS;Database=" + "DemoWebTwain" + ";Integrated Security=sspi;Persist Security Info=False";
string strExc = "";
string strImageExtName = "jpg";
try {
    String strImageID = request["iImageIndex"];
    //Get the image data from the database
    HttpRequest request = HttpContext.Current.Request;
    byte[] byFileData = null;
    if (strImageID != null && strImageID != "") {
        int iImageID = 0;
        try {
            iImageID = Convert.ToInt32(strImageID);
        } catch {
            return;
        }
        System.Data.SqlClient.SqlConnection sqlConnection = new System.Data.SqlClient.SqlConnection(strConnString);
        System.Data.SqlClient.SqlCommand sqlCmdObj = new System.Data.SqlClient.SqlCommand("SELECT imgImageData FROM " + "tblWebTwain" + " WHERE ID = " + iImageID.ToString(), sqlConnection);
        sqlConnection.Open();
        System.Data.SqlClient.SqlDataReader sdrRecordset = sqlCmdObj.ExecuteReader();
        if (sdrRecordset.Read()) {
            long iByteLength;
            iByteLength = sdrRecordset.GetBytes(0, 0, null, 0, int.MaxValue);
            byFileData = new byte[iByteLength];
            sdrRecordset.GetBytes(0, 0, byFileData, 0, Convert.ToInt32(iByteLength));
        }
        sdrRecordset.Close();
        sqlConnection.Close();
        sdrRecordset = null;
        sqlConnection = null;
    }
    Response.Clear();
    Response.Buffer = true;
    if (byFileData != null) {
        string fileNameEncode;
        fileNameEncode = HttpUtility.UrlEncode("downloadImg.jpg", System.Text.Encoding.UTF8);
        fileNameEncode = fileNameEncode.Replace("+", "%20");
        string appendedheader = "attachment;filename=" + fileNameEncode;
        Response.AppendHeader("Content-Disposition", appendedheader);
        Response.ContentType = "image/jpg";
        Response.OutputStream.Write(byFileData, 0, byFileData.Length);
    }
} catch (Exception ex) {}
  • On the client side, use the method HTTPDownloadEx to download the image. Put the action page DownloadFromDB.aspx as the source of the image (as the 2nd parameter String HTTPRemoteFile):
//downloadsource should be the correct path for
//the page DownloadFromDB.aspx plus any necessary
//parameters needed for fetching the image(s)
var downloadsource = DownloadFromDB.aspx + "?iImageIndex=0";
//You should know the type of the image you are
//downloading because it is downloading as a stream
//and Dynamic Web TWAIN needs the correct type
//in order to process the stream
DWObject.HTTPDownloadEx(strHTTPServer, downloadsource, EnumDWT_ImageType.IT_JPG);

Hide or Change the Progress Bar

To hide the progress bar during time-consuming operations like uploading/downloading, etc., set IfShowProgressBar and IfShowCancelDialogWhenImageTransfer to false.

For upload and download, you can use the event OnInternetTransferPercentage to customize your own progress bar. This event will return the percentage of the upload/download process

DWObject.RegisterEvent('OnInternetTransferPercentage', function(sPercentage){
    console.log(sPercentage); //Your code goes here.
});

Customize Prompts

To make the SDK easy-to-use, UI elements like prompts to download Dynamsoft Service are built-in. By default, the prompts come in English. To change it, the steps are

  1. Find and open the file dynamsoft.webtwain.install.js which can be found under the Resources folder.
  2. In this file you can change the wording and formatting of the prompts which is defined in the function _show_install_dialog and OnWebTWAINModuleDownloadManually.

Customize Display Language

The default display language for Dynamic Web TWAIN is English. From version 14.0, it's possible to config the language. The steps are

  1. Find and open the file dynamsoft.webtwain.config.js.
  2. Search for Dynamsoft.WebTwainEnv.CustomizableDisplayInfo and you can find the information which may appear when using the SDK. You can then change the words/sentences to your own native/target language which will then replace the default information.

Customize Built-in Image Editor

Dynamic Web TWAIN has a built-in image editor which shows up when you call the method ShowImageEditor. By default, the editor shows all of its buttons in its toolbar and it also takes up the full screen. From version 14.0, it's possible to configure the size of the toolbar as well as where it shows up.

To configure the toolbar, the steps are

  1. Find and open the file dynamsoft.webtwain.config.js.
  2. Search for buttons: { and you can find the place where you can change the titles of the buttons as well as whether certain buttons are hidden.

NOTE: To make sure the buttons show up nicely, the editor itself will hide buttons by group in case the editor window is not wide enough. Therefore, if the window is too narrow, some buttons might be hidden even if you have set them visible.

To configure where the editor shows up on the web page, use the method ShowImageEditor and specify the ID of the DIV to show the editor and its size.


Make Saved Images Small

To reduce the size of scanned/imported images when saving or uploading, you can try the following things

  1. Scan images in Grey or B&W by setting the property PixelType.
  2. Use a lower resolution by seeting the property Resolution. For existing images which were imported, you can also use the method SetDPI to change its DPI if it's too big.
  3. Choose a proper compression type for TIFF/PDF. The properties are TIFFCompressionType and PDFCompressionType.
  4. If you are uploading images as JPEG or JPEG-encoded PDF/TIFF, you can also set the property JPEGQuality to a lower value. The following is the sample code
DWObject.TIFFCompressionType = EnumDWT_TIFFCompressionType.TIFF_JPEG;
DWObject.JPEGQuality = 60;  // default value is 80

results matching ""

    No results matching ""

    results matching ""

      No results matching ""